name: Cookstyle
+
on:
- push
- pull_request
+ - workflow_dispatch
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
+ cancel-in-progress: true
+
jobs:
cookstyle:
name: Cookstyle
runs-on: ubuntu-latest
steps:
- name: Check out code
- uses: actions/checkout@v2.3.4
+ uses: actions/checkout@v4
- name: Setup ruby
- uses: actions/setup-ruby@v1.1.3
- - name: Cache gems
- uses: actions/cache@v2.1.6
+ uses: ruby/setup-ruby@v1
with:
- path: vendor/bundle
- key: bundle-${{ runner.OS }}-${{ hashFiles('Gemfile.lock') }}
- restore-keys: |
- bundle-${{ runner.OS }}-
- - name: Install gems
- run: |
- gem install bundler
- bundle config set deployment true
- bundle install --jobs 4 --retry 3
+ bundler-cache: true
- name: Run cookstyle
run: bundle exec cookstyle --format fuubar
name: Test Kitchen
+
on:
- push
- pull_request
+ - workflow_dispatch
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
+ cancel-in-progress: true
+
jobs:
kitchen:
name: Test Kitchen
- runs-on: ubuntu-latest
+ runs-on: ubuntu-22.04
+ permissions:
+ packages: read
strategy:
matrix:
suite:
- bind
- blog
- blogs
+ - chef
- civicrm
- clamav
+ - community
- db-backup
- db-base
- db-master
- dmca
- dns
- docker
- - donate
- elasticsearch
- exim
- fail2ban
- - forum
+ - foundation-board
+ - foundation-dwg
+ - foundation-mastodon
+ - foundation-mwg
+ - foundation-owg
+ - foundation-welcome
+ - foundation-wiki
- ftp
- geodns
- geoipupdate
- gps-tile
- hardware
- hot
- - incron
+ - ideditor
- irc
- kibana
- letsencrypt
- logstash-forwarder
- mail
- mailman
+ - matomo
- memcached
- - munin
- - munin-plugins
- - munin-server
- mysql
- networking
- nginx
- osmosis
- osqa
- otrs
+ - overpass
- passenger
- php
- php-apache
- php-fpm
- - piwik
- planet
+ - planet-aws
- planet-current
- planet-dump
- planet-notes
- serverinfo
- snmpd
- spamassassin
- - squid
- ssl
- - stateofthemap
+ - stateofthemap-container
+ - stateofthemap-wordpress
- subversion
- supybot
- switch2osm
- sysfs
- taginfo
- tile
- - tilecache
- tilelog
- tools
- trac
- - web-backend
- web-cgimap
- web-frontend
- web-rails
- wordpress
- wiki
os:
- - ubuntu-2004
+ - ubuntu-2204
include:
- - suite: trac
- os: ubuntu-1804
+ - os: ubuntu-2004
+ suite: mailman
+ - os: ubuntu-2004
+ suite: osqa
+ - os: debian-12
+ suite: imagery-tiler
exclude:
- - suite: trac
- os: ubuntu-2004
+ - suite: mailman
+ os: ubuntu-2204
+ - suite: osqa
+ os: ubuntu-2204
fail-fast: false
steps:
+ - name: Login to GitHub Container Registry
+ uses: docker/login-action@v3
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
- name: Check out code
- uses: actions/checkout@v2.3.4
+ uses: actions/checkout@v4
- name: Setup ruby
- uses: actions/setup-ruby@v1.1.3
- - name: Cache gems
- uses: actions/cache@v2.1.6
+ uses: ruby/setup-ruby@v1
with:
- path: vendor/bundle
- key: bundle-${{ runner.OS }}-${{ hashFiles('Gemfile.lock') }}
- restore-keys: |
- bundle-${{ runner.OS }}-
- - name: Disable apparmor for mysqld
- run: |
- sudo apt-get install apparmor-utils
- sudo aa-disable /usr/sbin/mysqld
- - name: Install gems
- run: |
- gem install bundler
- bundle config set deployment true
- bundle install --jobs 4 --retry 3
+ ruby-version: 3.1
+ bundler-cache: true
- name: Run kitchen test ${{ matrix.suite }}-${{ matrix.os }}
run: bundle exec kitchen test ${{ matrix.suite }}-${{ matrix.os }}
+ - name: Gather journal output
+ run: bundle exec kitchen exec ${{ matrix.suite }}-${{ matrix.os }} -c journalctl --since=yesterday
+ if: ${{ failure() }}
---
driver:
name: dokken
- chef_version: 16
+ chef_version: 18
+ volumes:
+ - /var/lib/docker
env:
- container=dokken
+ ipv6: true
+ ipv6_subnet: "fd95:8552:964c::/64"
+ dns:
+ - 1.1.1.1
+ - 8.8.8.8
+ - 8.8.4.4
+ - 1.0.0.1
transport:
name: dokken
name: dokken
chef_license: accept
data_bags_path: test/data_bags
+ slow_resource_report: true
+ clean_dokken_sandbox: true
verifier:
+ name: inspec
root_path: /opt/verifier
sudo: false
platforms:
- - name: ubuntu-18.04
+ - name: ubuntu-20.04
driver:
- image: dokken/ubuntu-18.04
+ image: ghcr.io/test-kitchen/dokken/ubuntu-20.04
privileged: true
pid_one_command: /bin/systemd
intermediate_instructions:
- RUN /usr/bin/apt-get update -y
- - name: ubuntu-20.04
+ - RUN /usr/bin/apt-get install -y eatmydata
+ - RUN echo /usr/lib/$(uname -m)-linux-gnu/libeatmydata.so >>/etc/ld.so.preload
+ - name: ubuntu-22.04
+ driver:
+ image: ghcr.io/test-kitchen/dokken/ubuntu-22.04
+ privileged: true
+ pid_one_command: /bin/systemd
+ intermediate_instructions:
+ - RUN /usr/bin/apt-get update -y
+ - RUN /usr/bin/apt-get install -y eatmydata
+ - RUN echo /usr/lib/$(uname -m)-linux-gnu/libeatmydata.so >>/etc/ld.so.preload
+ - name: debian-12
driver:
- image: dokken/ubuntu-20.04
+ image: ghcr.io/test-kitchen/dokken/debian-12
privileged: true
pid_one_command: /bin/systemd
intermediate_instructions:
- RUN /usr/bin/apt-get update -y
+ - RUN /usr/bin/apt-get install -y eatmydata
+ - RUN echo /usr/lib/$(uname -m)-linux-gnu/libeatmydata.so >>/etc/ld.so.preload
suites:
- name: accounts
- name: apt
run_list:
- recipe[apt::default]
+ - name: awscli
+ run_list:
+ - recipe[awscli::default]
- name: backup
run_list:
- recipe[backup::default]
- name: blogs
run_list:
- recipe[blogs::default]
+ - name: chef
+ run_list:
+ - recipe[chef::default]
- name: civicrm
run_list:
- recipe[civicrm::default]
- name: clamav
run_list:
- recipe[clamav::default]
+ - name: community
+ run_list:
+ - recipe[community::default]
- name: db-backup
run_list:
- recipe[db::backup]
test:
interface: eth0
role: internal
- address: 172.18.0.2
- prefix: 16
- gateway: 172.18.0.1
+ inet:
+ address: 172.18.0.2
+ prefix: 16
+ gateway: 172.18.0.1
roles:
external:
zone: test
- name: docker
run_list:
- recipe[docker::default]
- - name: donate
- run_list:
- - recipe[donate::default]
- name: elasticsearch
run_list:
- recipe[elasticsearch::default]
- name: fail2ban
run_list:
- recipe[fail2ban::default]
- - name: forum
+ - name: foundation-board
+ run_list:
+ - recipe[foundation::board]
+ - name: foundation-dwg
+ run_list:
+ - recipe[foundation::dwg]
+ - name: foundation-mastodon
+ run_list:
+ - recipe[foundation::mastodon]
+ - name: foundation-mwg
+ run_list:
+ - recipe[foundation::mwg]
+ - name: foundation-owg
+ run_list:
+ - recipe[foundation::owg]
+ - name: foundation-welcome
run_list:
- - recipe[forum::default]
+ - recipe[foundation::welcome]
+ - name: foundation-wiki
+ run_list:
+ - recipe[foundation::wiki]
- name: ftp
run_list:
- recipe[ftp::default]
interfaces:
test:
role: external
- address: 172.18.0.2
+ inet:
+ address: 172.18.0.2
+ prefix: 16
- name: geoipupdate
run_list:
- recipe[geoipupdate::default]
- name: hot
run_list:
- recipe[hot::default]
- - name: incron
+ - name: ideditor
+ run_list:
+ - recipe[ideditor::default]
+ - name: imagery-tiler
run_list:
- - recipe[incron::default]
+ - recipe[imagery::tiler]
- name: irc
run_list:
- recipe[irc::default]
- name: letsencrypt
run_list:
- recipe[letsencrypt::default]
- attributes:
- apt:
- sources:
- - openstreetmap
- name: logstash
run_list:
- recipe[logstash::default]
attributes:
logstash:
forwarder:
- filebeat.prospectors:
- - input_type: log
+ filebeat.inputs:
+ - type: filestream
+ id: apache
paths:
- /var/log/apache2/access.log
- type: apache
+ fields:
+ type: apache
+ fields_under_root: true
- name: mail
run_list:
- role[mail]
- name: mailman
run_list:
- recipe[mailman::default]
+ - name: matomo
+ run_list:
+ - recipe[matomo::default]
- name: memcached
run_list:
- recipe[memcached::default]
- - name: munin
- run_list:
- - recipe[munin::default]
- - name: munin-plugins
- run_list:
- - recipe[munin::plugins]
- - name: munin-server
- run_list:
- - recipe[munin::server]
- name: mysql
run_list:
- recipe[mysql::default]
- name: otrs
run_list:
- recipe[otrs::default]
+ - name: overpass
+ run_list:
+ - recipe[overpass::default]
- name: passenger
run_list:
- recipe[passenger::default]
- name: php-fpm
run_list:
- recipe[php::fpm]
- - name: piwik
- run_list:
- - recipe[piwik::default]
- name: planet
run_list:
- recipe[planet::default]
+ - name: planet-aws
+ run_list:
+ - recipe[planet::aws]
- name: planet-current
run_list:
- recipe[planet::current]
attributes:
postgresql:
versions:
- - 10
+ - 15
- name: prometheus
run_list:
- recipe[prometheus::default]
test:
interface: eth0
role: internal
- address: 172.18.0.2
- prefix: 16
- gateway: 172.18.0.1
+ inet:
+ address: 172.18.0.2
+ prefix: 16
+ gateway: 172.18.0.1
- name: prometheus-server
run_list:
- recipe[prometheus::server]
- name: spamassassin
run_list:
- recipe[spamassassin::default]
- - name: squid
- run_list:
- - recipe[squid::default]
- name: ssl
run_list:
- recipe[ssl::default]
- - name: stateofthemap
+ - name: stateofthemap-container
+ run_list:
+ - recipe[stateofthemap::container]
+ - name: stateofthemap-wordpress
run_list:
- - recipe[stateofthemap::default]
+ - recipe[stateofthemap::wordpress]
- name: subversion
run_list:
- recipe[subversion::default]
- name: tile
run_list:
- recipe[tile::default]
- - name: tilecache
- run_list:
- - recipe[tilecache::default]
- name: tilelog
run_list:
- recipe[tilelog::default]
- - name: timescaledb
- run_list:
- - recipe[timescaledb::default]
- name: tools
run_list:
- recipe[tools::default]
- name: trac
run_list:
- recipe[trac::default]
- - name: web-backend
- run_list:
- - recipe[web::backend]
- name: web-cgimap
run_list:
- recipe[web::cgimap]
inherit_from: .rubocop_todo.yml
AllCops:
- TargetRubyVersion: 2.7
+ TargetRubyVersion: 3.1
-ChefModernize/IncludingAptDefaultRecipe:
+Chef/Modernize/IncludingAptDefaultRecipe:
+ Enabled: false
+
+Chef/Modernize/CronDFileOrTemplate:
Enabled: false
Layout/ExtraSpacing:
You should fork the project into your own repo, create a topic branch
there and then make one or more pull requests back to the openstreetmap/chef repository.
Your pull requests will then be reviewed and discussed.
+
+## Running the Infrastructure Tests locally
+
+- **[Cookstyle](https://docs.chef.io/workstation/cookstyle/)** is used for linting, ensuring that our Chef recipes follow style guidelines and best practices.
+- **[Test Kitchen](https://kitchen.ci/)** combined with **InSpec** and [Dokken](https://github.com/test-kitchen/kitchen-dokken) is used to verify the functionality of our Chef code, ensuring it behaves as expected.
+
+The following guidelines are to help set up and run these checks locally:
+
+#### **1. Install Docker**
+- Visit [Docker's official site](https://www.docker.com/products/docker-desktop) to download and install Docker.
+
+#### **2. Install Homebrew (Apple MacOS only)**
+- Install Homebrew by following the instructions [here](https://brew.sh/).
+
+#### **3. Install rbenv (recommended)**
+- Install rbenv by following the instructions [here](https://github.com/rbenv/rbenv#installation).
+
+rbenv is a ruby version manager. rbenv allows projects to use a different version of ruby than the version of install with your operating system.
+
+> *Note on rbenv: While we recommend using rbenv for managing Ruby versions, it's not strictly necessary. If you have Ruby already installed feel free to use that. If you're not using rbenv, simply omit the `rbenv exec` prefix from the commands below.*
+
+#### **4. Increase File Limit (Important for MacOS)**
+
+To avoid errors when running tests on MacOS, you might need to increase the number of files your system can open at once. Here's how:
+
+1. Run the command:
+```bash
+ulimit -n 1024
+```
+2. To make the change permanent, add the above line to either `~/.zshrc` or `~/.bash_profile`, depending on your shell.
+
+**Note:** MacOS has a low default limit of just 256 open files. If you exceed this while testing, you'll see an error like: `Too many open files - getcwd (Errno::EMFILE)`. This step helps prevent that.
+
+#### **5. Install Required Ruby Version (recommended)**
+Navigate to the git checkout of the OpenStreetMap chef repo and run:
+```bash
+rbenv install
+```
+This will install the recommended version of ruby for running the tests. The recommended version of ruby is defined in the [.ruby-version](.ruby-version) file.
+
+#### **6. Install Dependencies with Bundler**
+```bash
+rbenv exec gem install bundler
+rbenv exec bundler install
+```
+This will install the [bundler](https://bundler.io/), the ruby gem packages manager, and then uses `bundler`` to install the required gem packages for the tests.
+
+#### **7. Run Cookstyle for Linting and Style Checks**
+```bash
+rbenv exec bundle exec cookstyle
+```
+This will run [cookstyle](https://docs.chef.io/workstation/cookstyle/) a linting tool which reports on any linting issues.
+
+> *Automatically run cookstyle lint: We have a sample [git pre-commit hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) in the `hooks/pre-commit` file which can be copied to the local checkout of this repo to the file `.git/hooks/pre-commit` to ensure the lint passes when running a git commit.*
+
+#### **8. List Available Tests**
+```bash
+rbenv exec bundler exec kitchen list
+```
+This lists the [Test Kitchen](https://kitchen.ci/) tests which are available. The list of tests is generated from the definitions in the [.kitchen.yml](.kitchen.yml) file. The individual tests are written in [InSpec](https://docs.chef.io/inspec/) and are stored in the `test/integration/` directory.
+
+#### **9. Run an Example Test**
+```bash
+rbenv exec bundler exec kitchen test dns-ubuntu-2204
+```
+This runs the [Test Kitchen](https://kitchen.ci/) [InSpec](https://docs.chef.io/inspec/) `dns` tests using the `Ubuntu 22.04` platform. The tests are run inside a Docker container using the Test Kitchen [Dokken driver](https://github.com/test-kitchen/kitchen-dokken).
# Basic Dockerfile to run cookstyle linting
# run: docker build -t chef-test .
-FROM ruby:2.7-alpine as build
+FROM ruby:3.1-alpine as build
# Add Gem build requirements
RUN apk add --no-cache build-base
gem "cookstyle"
gem "kitchen-dokken"
-gem "serverspec"
+gem "kitchen-inspec"
gem "test-kitchen"
GEM
remote: https://rubygems.org/
specs:
+ activesupport (7.1.3.2)
+ base64
+ bigdecimal
+ concurrent-ruby (~> 1.0, >= 1.0.2)
+ connection_pool (>= 2.2.5)
+ drb
+ i18n (>= 1.6, < 2)
+ minitest (>= 5.1)
+ mutex_m
+ tzinfo (~> 2.0)
+ addressable (2.8.6)
+ public_suffix (>= 2.0.2, < 6.0)
ast (2.4.2)
+ aws-eventstream (1.3.0)
+ aws-partitions (1.863.0)
+ aws-sdk-accessanalyzer (1.44.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-account (1.20.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-alexaforbusiness (1.67.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-amplify (1.54.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-apigateway (1.90.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-apigatewayv2 (1.53.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-applicationautoscaling (1.79.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-athena (1.79.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-autoscaling (1.102.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-batch (1.79.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-budgets (1.62.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-cloudformation (1.97.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-cloudfront (1.86.1)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-cloudhsm (1.50.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-cloudhsmv2 (1.53.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-cloudtrail (1.74.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-cloudwatch (1.83.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-cloudwatchevents (1.69.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-cloudwatchlogs (1.77.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-codecommit (1.62.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-codedeploy (1.62.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-codepipeline (1.67.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-cognitoidentity (1.51.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-cognitoidentityprovider (1.85.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-configservice (1.103.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-core (3.190.3)
+ aws-eventstream (~> 1, >= 1.3.0)
+ aws-partitions (~> 1, >= 1.651.0)
+ aws-sigv4 (~> 1.8)
+ jmespath (~> 1, >= 1.6.1)
+ aws-sdk-costandusagereportservice (1.53.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-databasemigrationservice (1.91.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-dynamodb (1.98.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-ec2 (1.429.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-ecr (1.68.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-ecrpublic (1.25.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-ecs (1.135.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-efs (1.71.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-eks (1.95.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-elasticache (1.95.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-elasticbeanstalk (1.63.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-elasticloadbalancing (1.51.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-elasticloadbalancingv2 (1.96.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-elasticsearchservice (1.79.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-emr (1.81.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-eventbridge (1.54.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-firehose (1.60.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-glue (1.165.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-guardduty (1.85.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-iam (1.92.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-kafka (1.67.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-kinesis (1.54.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-kms (1.76.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-lambda (1.113.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-macie2 (1.64.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-mq (1.58.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-networkfirewall (1.39.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-networkmanager (1.40.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-organizations (1.83.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-ram (1.52.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-rds (1.208.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-redshift (1.107.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-route53 (1.83.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-route53domains (1.54.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-route53resolver (1.51.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-s3 (1.141.0)
+ aws-sdk-core (~> 3, >= 3.189.0)
+ aws-sdk-kms (~> 1)
+ aws-sigv4 (~> 1.8)
+ aws-sdk-s3control (1.74.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-secretsmanager (1.87.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-securityhub (1.98.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-servicecatalog (1.90.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-ses (1.58.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-shield (1.60.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-signer (1.50.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-simpledb (1.42.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv2 (~> 1.0)
+ aws-sdk-sms (1.52.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-sns (1.70.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-sqs (1.69.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-ssm (1.162.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-states (1.63.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-synthetics (1.39.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-transfer (1.86.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-waf (1.58.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-wafv2 (1.74.0)
+ aws-sdk-core (~> 3, >= 3.188.0)
+ aws-sigv4 (~> 1.1)
+ aws-sigv2 (1.2.0)
+ aws-sigv4 (1.8.0)
+ aws-eventstream (~> 1, >= 1.0.2)
+ azure_graph_rbac (0.17.2)
+ ms_rest_azure (~> 0.12.0)
+ azure_mgmt_key_vault (0.17.7)
+ ms_rest_azure (~> 0.12.0)
+ azure_mgmt_resources (0.18.2)
+ ms_rest_azure (~> 0.12.0)
+ azure_mgmt_security (0.19.0)
+ ms_rest_azure (~> 0.12.0)
+ azure_mgmt_storage (0.23.0)
+ ms_rest_azure (~> 0.12.0)
+ base64 (0.2.0)
bcrypt_pbkdf (1.1.0)
+ bigdecimal (3.1.7)
+ bson (4.15.0)
builder (3.2.4)
- chef-utils (17.2.29)
+ chef-config (18.4.12)
+ addressable
+ chef-utils (= 18.4.12)
+ fuzzyurl
+ mixlib-config (>= 2.2.12, < 4.0)
+ mixlib-shellout (>= 2.0, < 4.0)
+ tomlrb (~> 1.2)
+ chef-telemetry (1.1.1)
+ chef-config
+ concurrent-ruby (~> 1.0)
+ chef-utils (18.4.12)
concurrent-ruby
- concurrent-ruby (1.1.9)
- cookstyle (7.13.0)
- rubocop (= 1.15.0)
- diff-lcs (1.4.4)
- docker-api (2.1.0)
+ coderay (1.1.3)
+ concurrent-ruby (1.2.3)
+ connection_pool (2.4.1)
+ cookstyle (7.32.8)
+ rubocop (= 1.25.1)
+ declarative (0.0.20)
+ diff-lcs (1.5.1)
+ docker-api (2.2.0)
excon (>= 0.47.0)
multi_json
- ed25519 (1.2.4)
- erubi (1.10.0)
- excon (0.81.0)
- ffi (1.15.1)
+ domain_name (0.6.20240107)
+ drb (2.2.1)
+ dry-configurable (1.1.0)
+ dry-core (~> 1.0, < 2)
+ zeitwerk (~> 2.6)
+ dry-core (1.0.1)
+ concurrent-ruby (~> 1.0)
+ zeitwerk (~> 2.6)
+ dry-inflector (1.0.0)
+ dry-logic (1.5.0)
+ concurrent-ruby (~> 1.0)
+ dry-core (~> 1.0, < 2)
+ zeitwerk (~> 2.6)
+ dry-struct (1.6.0)
+ dry-core (~> 1.0, < 2)
+ dry-types (>= 1.7, < 2)
+ ice_nine (~> 0.11)
+ zeitwerk (~> 2.6)
+ dry-types (1.7.2)
+ bigdecimal (~> 3.0)
+ concurrent-ruby (~> 1.0)
+ dry-core (~> 1.0)
+ dry-inflector (~> 1.0)
+ dry-logic (~> 1.4)
+ zeitwerk (~> 2.6)
+ ed25519 (1.3.0)
+ erubi (1.12.0)
+ excon (0.110.0)
+ faraday (1.10.3)
+ faraday-em_http (~> 1.0)
+ faraday-em_synchrony (~> 1.0)
+ faraday-excon (~> 1.1)
+ faraday-httpclient (~> 1.0)
+ faraday-multipart (~> 1.0)
+ faraday-net_http (~> 1.0)
+ faraday-net_http_persistent (~> 1.0)
+ faraday-patron (~> 1.0)
+ faraday-rack (~> 1.0)
+ faraday-retry (~> 1.0)
+ ruby2_keywords (>= 0.0.4)
+ faraday-cookie_jar (0.0.7)
+ faraday (>= 0.8.0)
+ http-cookie (~> 1.0.0)
+ faraday-em_http (1.0.0)
+ faraday-em_synchrony (1.0.0)
+ faraday-excon (1.1.0)
+ faraday-follow_redirects (0.3.0)
+ faraday (>= 1, < 3)
+ faraday-httpclient (1.0.1)
+ faraday-multipart (1.0.4)
+ multipart-post (~> 2)
+ faraday-net_http (1.0.1)
+ faraday-net_http_persistent (1.2.0)
+ faraday-patron (1.0.0)
+ faraday-rack (1.0.0)
+ faraday-retry (1.0.3)
+ faraday_middleware (1.2.0)
+ faraday (~> 1.0)
+ ffi (1.16.3)
+ fuzzyurl (0.9.0)
+ google-api-client (0.52.0)
+ addressable (~> 2.5, >= 2.5.1)
+ googleauth (~> 0.9)
+ httpclient (>= 2.8.1, < 3.0)
+ mini_mime (~> 1.0)
+ representable (~> 3.0)
+ retriable (>= 2.0, < 4.0)
+ rexml
+ signet (~> 0.12)
+ googleauth (0.14.0)
+ faraday (>= 0.17.3, < 2.0)
+ jwt (>= 1.4, < 3.0)
+ memoist (~> 0.16)
+ multi_json (~> 1.11)
+ os (>= 0.9, < 2.0)
+ signet (~> 0.14)
gssapi (1.3.1)
ffi (>= 1.0.1)
- gyoku (1.3.1)
+ gyoku (1.4.0)
builder (>= 2.1.2)
+ rexml (~> 3.0)
+ hashdiff (1.0.1)
+ hashie (5.0.0)
+ highline (2.1.0)
+ http-cookie (1.0.5)
+ domain_name (~> 0.5)
httpclient (2.8.3)
- kitchen-dokken (2.12.1)
+ i18n (1.14.4)
+ concurrent-ruby (~> 1.0)
+ ice_nine (0.11.2)
+ inifile (3.0.0)
+ inspec (5.22.40)
+ cookstyle
+ faraday_middleware (>= 0.12.2, < 1.3)
+ inspec-core (= 5.22.40)
+ mongo (= 2.13.2)
+ progress_bar (~> 1.3.3)
+ rake
+ train (~> 3.10)
+ train-aws (~> 0.2)
+ train-habitat (~> 0.1)
+ train-kubernetes (~> 0.1)
+ train-winrm (~> 0.2)
+ inspec-core (5.22.40)
+ addressable (~> 2.4)
+ chef-telemetry (~> 1.0, >= 1.0.8)
+ faraday (>= 1, < 3)
+ faraday-follow_redirects (~> 0.3)
+ hashie (>= 3.4, < 6.0)
+ license-acceptance (>= 0.2.13, < 3.0)
+ method_source (>= 0.8, < 2.0)
+ mixlib-log (~> 3.0)
+ multipart-post (~> 2.0)
+ parallel (~> 1.9)
+ parslet (>= 1.5, < 3.0)
+ pry (~> 0.13)
+ rspec (>= 3.9, <= 3.12)
+ rspec-its (~> 1.2)
+ rubyzip (>= 1.2.2, < 3.0)
+ semverse (~> 3.0)
+ sslshake (~> 1.2)
+ thor (>= 0.20, < 1.3.0)
+ tomlrb (>= 1.2, < 2.1)
+ train-core (~> 3.10)
+ tty-prompt (~> 0.17)
+ tty-table (~> 0.10)
+ jmespath (1.6.2)
+ json (2.7.1)
+ jsonpath (1.1.5)
+ multi_json
+ jwt (2.8.1)
+ base64
+ k8s-ruby (0.16.0)
+ dry-configurable
+ dry-struct
+ dry-types
+ excon (~> 0.71)
+ hashdiff (~> 1.0.0)
+ jsonpath (~> 1.1)
+ recursive-open-struct (~> 1.1.3)
+ yajl-ruby (~> 1.4.0)
+ yaml-safe_load_stream3
+ kitchen-dokken (2.20.4)
docker-api (>= 1.33, < 3)
lockfile (~> 2.1)
- test-kitchen (>= 1.15, < 3)
+ test-kitchen (>= 1.15, < 4)
+ kitchen-inspec (2.6.2)
+ hashie (>= 3.4, <= 5.0)
+ inspec (>= 2.2.64, < 6.0)
+ test-kitchen (>= 2.7, < 4)
license-acceptance (2.1.13)
pastel (~> 0.7)
tomlrb (>= 1.2, < 3.0)
tty-prompt (~> 0.20)
little-plugger (1.1.4)
lockfile (2.1.3)
- logging (2.3.0)
+ logging (2.3.1)
little-plugger (~> 1.1)
multi_json (~> 1.14)
- mixlib-install (3.12.11)
+ memoist (0.16.2)
+ method_source (1.0.0)
+ mini_mime (1.1.5)
+ minitest (5.22.3)
+ mixlib-config (3.0.27)
+ tomlrb
+ mixlib-install (3.12.30)
mixlib-shellout
mixlib-versioning
thor
- mixlib-shellout (3.2.5)
+ mixlib-log (3.0.9)
+ mixlib-shellout (3.2.7)
chef-utils
mixlib-versioning (1.2.12)
+ mongo (2.13.2)
+ bson (>= 4.8.2, < 5.0.0)
+ ms_rest (0.7.6)
+ concurrent-ruby (~> 1.0)
+ faraday (>= 0.9, < 2.0.0)
+ timeliness (~> 0.3.10)
+ ms_rest_azure (0.12.0)
+ concurrent-ruby (~> 1.0)
+ faraday (>= 0.9, < 2.0.0)
+ faraday-cookie_jar (~> 0.0.6)
+ ms_rest (~> 0.7.6)
multi_json (1.15.0)
- net-scp (3.0.0)
- net-ssh (>= 2.6.5, < 7.0.0)
- net-ssh (6.1.0)
+ multipart-post (2.4.0)
+ mutex_m (0.2.0)
+ net-scp (4.0.0)
+ net-ssh (>= 2.6.5, < 8.0.0)
+ net-ssh (7.2.3)
net-ssh-gateway (2.0.0)
net-ssh (>= 4.0.0)
- net-telnet (0.1.1)
- nori (2.6.0)
- parallel (1.20.1)
- parser (3.0.1.1)
+ nori (2.7.0)
+ bigdecimal
+ options (2.3.2)
+ os (1.1.4)
+ parallel (1.24.0)
+ parser (3.3.0.5)
ast (~> 2.4.1)
+ racc
+ parslet (2.0.0)
pastel (0.8.0)
tty-color (~> 0.5)
- rainbow (3.0.0)
- regexp_parser (2.1.1)
- rexml (3.2.5)
- rspec (3.10.0)
- rspec-core (~> 3.10.0)
- rspec-expectations (~> 3.10.0)
- rspec-mocks (~> 3.10.0)
- rspec-core (3.10.1)
- rspec-support (~> 3.10.0)
- rspec-expectations (3.10.1)
+ progress_bar (1.3.3)
+ highline (>= 1.6, < 3)
+ options (~> 2.3.0)
+ pry (0.14.2)
+ coderay (~> 1.1)
+ method_source (~> 1.0)
+ public_suffix (5.0.4)
+ racc (1.7.3)
+ rainbow (3.1.1)
+ rake (13.1.0)
+ recursive-open-struct (1.1.3)
+ regexp_parser (2.9.0)
+ representable (3.2.0)
+ declarative (< 0.1.0)
+ trailblazer-option (>= 0.1.1, < 0.2.0)
+ uber (< 0.2.0)
+ retriable (3.1.2)
+ rexml (3.2.6)
+ rspec (3.12.0)
+ rspec-core (~> 3.12.0)
+ rspec-expectations (~> 3.12.0)
+ rspec-mocks (~> 3.12.0)
+ rspec-core (3.12.3)
+ rspec-support (~> 3.12.0)
+ rspec-expectations (3.12.4)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.10.0)
+ rspec-support (~> 3.12.0)
rspec-its (1.3.0)
rspec-core (>= 3.0.0)
rspec-expectations (>= 3.0.0)
- rspec-mocks (3.10.2)
+ rspec-mocks (3.12.7)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.10.0)
- rspec-support (3.10.2)
- rubocop (1.15.0)
+ rspec-support (~> 3.12.0)
+ rspec-support (3.12.2)
+ rubocop (1.25.1)
parallel (~> 1.10)
- parser (>= 3.0.0.0)
+ parser (>= 3.1.0.0)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml
- rubocop-ast (>= 1.5.0, < 2.0)
+ rubocop-ast (>= 1.15.1, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0)
- rubocop-ast (1.6.0)
- parser (>= 3.0.1.1)
- ruby-progressbar (1.11.0)
+ rubocop-ast (1.31.2)
+ parser (>= 3.3.0.4)
+ ruby-progressbar (1.13.0)
+ ruby2_keywords (0.0.5)
rubyntlm (0.6.3)
- rubyzip (2.3.0)
- serverspec (2.41.5)
- multi_json
- rspec (~> 3.0)
- rspec-its
- specinfra (~> 2.72)
- sfl (2.3)
- specinfra (2.82.25)
- net-scp
- net-ssh (>= 2.7)
- net-telnet (= 0.1.1)
- sfl
+ rubyzip (2.3.2)
+ semverse (3.0.2)
+ signet (0.19.0)
+ addressable (~> 2.8)
+ faraday (>= 0.17.5, < 3.a)
+ jwt (>= 1.5, < 3.0)
+ multi_json (~> 1.10)
+ sslshake (1.3.1)
strings (0.2.1)
strings-ansi (~> 0.2)
unicode-display_width (>= 1.5, < 3.0)
unicode_utils (~> 1.4)
strings-ansi (0.2.0)
- test-kitchen (2.12.0)
+ test-kitchen (3.6.0)
bcrypt_pbkdf (~> 1.0)
chef-utils (>= 16.4.35)
ed25519 (~> 1.2)
license-acceptance (>= 1.0.11, < 3.0)
mixlib-install (~> 3.6)
mixlib-shellout (>= 1.2, < 4.0)
- net-scp (>= 1.1, < 4.0)
- net-ssh (>= 2.9, < 7.0)
+ net-scp (>= 1.1, < 5.0)
+ net-ssh (>= 2.9, < 8.0)
net-ssh-gateway (>= 1.2, < 3.0)
thor (>= 0.19, < 2.0)
winrm (~> 2.0)
winrm-elevated (~> 1.0)
winrm-fs (~> 1.1)
- thor (1.1.0)
- tomlrb (2.0.1)
+ thor (1.2.2)
+ timeliness (0.3.10)
+ tomlrb (1.3.0)
+ trailblazer-option (0.1.2)
+ train (3.11.0)
+ activesupport (>= 6.0.3.1)
+ azure_graph_rbac (~> 0.16)
+ azure_mgmt_key_vault (~> 0.17)
+ azure_mgmt_resources (~> 0.15)
+ azure_mgmt_security (~> 0.18)
+ azure_mgmt_storage (~> 0.18)
+ docker-api (>= 1.26, < 3.0)
+ google-api-client (>= 0.23.9, <= 0.52.0)
+ googleauth (>= 0.6.6, <= 0.14.0)
+ inifile (~> 3.0)
+ train-core (= 3.11.0)
+ train-winrm (~> 0.2)
+ train-aws (0.2.41)
+ aws-partitions (~> 1.863.0)
+ aws-sdk-accessanalyzer (~> 1.44.0)
+ aws-sdk-account (~> 1.20.0)
+ aws-sdk-alexaforbusiness (~> 1.67.0)
+ aws-sdk-amplify (~> 1.54.0)
+ aws-sdk-apigateway (~> 1.90.0)
+ aws-sdk-apigatewayv2 (~> 1.53.0)
+ aws-sdk-applicationautoscaling (~> 1.79.0)
+ aws-sdk-athena (>= 1.78, < 1.80)
+ aws-sdk-autoscaling (= 1.102.0)
+ aws-sdk-batch (~> 1.79.0)
+ aws-sdk-budgets (~> 1.62.0)
+ aws-sdk-cloudformation (>= 1.96, < 1.98)
+ aws-sdk-cloudfront (~> 1.86.0)
+ aws-sdk-cloudhsm (~> 1.50.0)
+ aws-sdk-cloudhsmv2 (~> 1.53.0)
+ aws-sdk-cloudtrail (~> 1.74.0)
+ aws-sdk-cloudwatch (~> 1.83.0)
+ aws-sdk-cloudwatchevents (~> 1.69.0)
+ aws-sdk-cloudwatchlogs (~> 1.75)
+ aws-sdk-codecommit (~> 1.62.0)
+ aws-sdk-codedeploy (~> 1.62.0)
+ aws-sdk-codepipeline (~> 1.67.0)
+ aws-sdk-cognitoidentity (~> 1.51.0)
+ aws-sdk-cognitoidentityprovider (~> 1.84)
+ aws-sdk-configservice (~> 1.103.0)
+ aws-sdk-core (~> 3.190.0)
+ aws-sdk-costandusagereportservice (~> 1.53.0)
+ aws-sdk-databasemigrationservice (~> 1.91.0)
+ aws-sdk-dynamodb (~> 1.98.0)
+ aws-sdk-ec2 (>= 1.427, < 1.430)
+ aws-sdk-ecr (~> 1.68.0)
+ aws-sdk-ecrpublic (~> 1.25.0)
+ aws-sdk-ecs (~> 1.135.0)
+ aws-sdk-efs (~> 1.71.0)
+ aws-sdk-eks (~> 1.95.0)
+ aws-sdk-elasticache (~> 1.95.0)
+ aws-sdk-elasticbeanstalk (~> 1.63.0)
+ aws-sdk-elasticloadbalancing (~> 1.51.0)
+ aws-sdk-elasticloadbalancingv2 (~> 1.96.0)
+ aws-sdk-elasticsearchservice (~> 1.79.0)
+ aws-sdk-emr (~> 1.81.0)
+ aws-sdk-eventbridge (~> 1.54.0)
+ aws-sdk-firehose (~> 1.60.0)
+ aws-sdk-glue (~> 1.164)
+ aws-sdk-guardduty (~> 1.85.0)
+ aws-sdk-iam (~> 1.92.0)
+ aws-sdk-kafka (~> 1.67.0)
+ aws-sdk-kinesis (~> 1.54.0)
+ aws-sdk-kms (~> 1.74)
+ aws-sdk-lambda (~> 1.113.0)
+ aws-sdk-macie2 (~> 1.64.0)
+ aws-sdk-mq (~> 1.58.0)
+ aws-sdk-networkfirewall (~> 1.39.0)
+ aws-sdk-networkmanager (~> 1.40.0)
+ aws-sdk-organizations (~> 1.83.0)
+ aws-sdk-ram (~> 1.52.0)
+ aws-sdk-rds (~> 1.208.0)
+ aws-sdk-redshift (~> 1.107.0)
+ aws-sdk-route53 (~> 1.83.0)
+ aws-sdk-route53domains (~> 1.54.0)
+ aws-sdk-route53resolver (~> 1.51.0)
+ aws-sdk-s3 (~> 1.141.0)
+ aws-sdk-s3control (~> 1.74.0)
+ aws-sdk-secretsmanager (~> 1.87.0)
+ aws-sdk-securityhub (~> 1.98.0)
+ aws-sdk-servicecatalog (~> 1.90.0)
+ aws-sdk-ses (~> 1.58.0)
+ aws-sdk-shield (~> 1.60.0)
+ aws-sdk-signer (~> 1.50.0)
+ aws-sdk-simpledb (~> 1.42.0)
+ aws-sdk-sms (~> 1.52.0)
+ aws-sdk-sns (~> 1.70.0)
+ aws-sdk-sqs (~> 1.69.0)
+ aws-sdk-ssm (~> 1.162.0)
+ aws-sdk-states (~> 1.63.0)
+ aws-sdk-synthetics (~> 1.39.0)
+ aws-sdk-transfer (~> 1.86.0)
+ aws-sdk-waf (~> 1.58.0)
+ aws-sdk-wafv2 (~> 1.74.0)
+ train-core (3.11.0)
+ addressable (~> 2.5)
+ ffi (!= 1.13.0)
+ json (>= 1.8, < 3.0)
+ mixlib-shellout (>= 2.0, < 4.0)
+ net-scp (>= 1.2, < 5.0)
+ net-ssh (>= 2.9, < 8.0)
+ train-habitat (0.2.22)
+ train-kubernetes (0.2.1)
+ k8s-ruby (~> 0.16.0)
+ train (~> 3.0)
+ train-winrm (0.2.13)
+ winrm (>= 2.3.6, < 3.0)
+ winrm-elevated (~> 1.2.2)
+ winrm-fs (~> 1.0)
tty-box (0.7.0)
pastel (~> 0.8)
strings (~> 0.2.0)
tty-cursor (~> 0.7)
tty-screen (~> 0.8)
wisper (~> 2.0)
- tty-screen (0.8.1)
- unicode-display_width (2.0.0)
+ tty-screen (0.8.2)
+ tty-table (0.12.0)
+ pastel (~> 0.8)
+ strings (~> 0.2.0)
+ tty-screen (~> 0.8)
+ tzinfo (2.0.6)
+ concurrent-ruby (~> 1.0)
+ uber (0.1.0)
+ unicode-display_width (2.5.0)
unicode_utils (1.4.0)
winrm (2.3.6)
builder (>= 2.1.2)
rubyzip (~> 2.0)
winrm (~> 2.0)
wisper (2.0.1)
+ yajl-ruby (1.4.3)
+ yaml-safe_load_stream3 (0.1.2)
+ zeitwerk (2.6.13)
PLATFORMS
ruby
DEPENDENCIES
cookstyle
kitchen-dokken
- serverspec
+ kitchen-inspec
test-kitchen
BUNDLED WITH
We make extensive use of roles to configure the servers. In general we have:
-## Server-specific roles (e.g. [katla.rb](roles/katla.rb))
+## Server-specific roles (e.g. [faffy.rb](roles/faffy.rb))
These deal with particular setup or quirks of a server, such as its IP address. They also include roles representing the service they are performing, and the location they are in and any particular hardware they have that needs configuration.
All our servers are [named after dragons](https://wiki.openstreetmap.org/wiki/Servers/Name_Ideas).
-## Hardware-specific roles (e.g. [tyan-s7010.rb](roles/tyan-s7010.rb))
+## Hardware-specific roles (e.g. [hp-g9.rb](roles/hp-g9.rb))
Covers anything specific to a certain piece of hardware, like a motherboard, that could apply to multiple machines.
-## Location-specific roles (e.g. [equinix.rb](roles/equinix.rb))
+## Location-specific roles (e.g. [equinix-dub.rb](roles/equinix-dub.rb))
These form a hierarchy of datacentres, organisations, and countries where our servers are located.
# Contributing
-Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for more details.
+Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for more details. The guide also includes details on how to run the tests locally.
# Contact Us
* Twitter: [@OSM_Tech](https://twitter.com/OSM_Tech)
+* Mastodon / Fediverse: [@OSM_Tech](https://en.osm.town/@osm_tech)
* IRC: [#OSM-Dev on irc.oftc.net](https://irc.openstreetmap.org/)
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef - use authorized_keys2 instead
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEYfJbizJ99jRXzyNcIbPYFH874Qj2YM7FVqbomq/hDB github-key
--- /dev/null
+# Generated by /usr/bin/select-editor
+SELECTED_EDITOR="/usr/bin/vim.basic"
# DO NOT EDIT - This file is being maintained by Chef - use authorized_keys2 instead
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6Hw67b4cRzXDvs88XSuKpXTJmFyietVqaQvJRedQflurHay5lGdFyzfPF0P+mG9l5O/qlKzXo5xvZNe6YOGcMCuxzOYiw/bAkEd7oHYVXVJr8jWL2zqusBmf5dLZDEjMtUX9w6IQWiuSvm3To3Fsohn2UjUqEi5aULu6h39O1JtcdtmIvjB4iTmIO4Eme8FxubktDImyCvwOAJVsYQASljeaTDa+31ANqMDehXZSRjFKaVECw1RNyvYclmkbj8rLiw648/IV9xRi/SMtZlNyxrcIKQ6hKmmiyaBA6a5QEqWj7OMVYCECAoNwlWKhBmkMx7fwOh1eKKOLFeFz2kdSt grant@home-desktop-key
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDuVegqS8l8WgH1T1LMGyJ4OvPeI5Kek5f5bYsHy62DLOhd4aDHCjJPegfiKCdpYde/b2kOQuwG90cl1a+6DDvNXvIDarQvfNzNWGONOtb+NM0/+IuAfSeonh8ROWRLW5ciOQi0PuPGnjD9vYdFMKtCh1lyi9KOq9DJNR0HFqEJgoZg8BoclAUdtgPzYU/fVpgwAS5mdBUTIQga3CbVsRcTWLPFKNlgY46eWYEKb9XqZIoa5AlxqH6AtYjaUQBdGzRpo/PW71VZzpZMP/dhf6illQBUyFJXL+PyVZGsckq94fkb6j3E5OkuGT55o4fEVLQaIDh2sIUB5n2emnP5On44kNTCPZiAMAC2weLv9PD7RFgTuxVTa1WsxbDqqaTueHJH1P+K4TNx2w0wfTfxqXjXKQPwGED1+xHWwOQoWT9eSarvUQF1jtQdseNsljPkJtpTiD2CHIUuCohYm0DxGYbQSl7uTLDK5HfuMMhAfBry/kNDb7CFTWKzN98Zbam8fx7e9TnCoL4MOMR8GOZyw/ITMbjmWRV5JGFfNUvqrteb9DLh99ZNDrcAawoESFLQTaXGPNYwCMcsxHxZAo8obfRGM/RbGvS+njfib6tkMwh6H/7uA1MPVLEbLejosMUzylDcfaoqGB5SryzZSVO0f7lx4JadQDCAimGBb0N3Fem8Rw== grant.slater@FRIDAY
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGW+K3RYYU26wSOp0DWA4OA94UeX9AZdk8aaaiV1KopY grant@home
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG+dY7nSVDShpfzDrgs1UaDeFbQUlXVWl4eECFu0Zo3a grant.slater@LONGS22-M
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef - use authorized_keys2 instead
+ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAB9jIwQu1TmXcQH6FXEz53fkTX3abCgjflwdESnaR5qKw6hUcvAIjPXiGLFGdl+nR56aCbQrbXQVF3Hug2+057xcAEAhFj0aIOoDhgEkZ0uK4GIElZjCUugYLt3AbQXTRpEXtXaL1wzyBmFqbTMOxDOzaif+PYWwDHC1yo1C5jhSlRmRg== jesus@Mac-mini-de-Jesus.local
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef - use authorized_keys2 instead
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCYd3z5L8YQXRw3JHXwD0KyTdfWncom7UPAP3BcrfUK/oJXFAE6w4w4nsYHk4axRddIKLXYXl5guine/hd7uBk77mqVYSi4JpCDhYt8cIvAd6xHOmWEQwU3Yjvov3XcKOz304sD93pcynBXwpUxih4k3UifgUJz7Ire0f99FaOQ5+yI6qVMEcOReNGgtR3k7vbZXJhzNanKaZoUVeA/PAZx+Zv9cOXvmfgsYSmU6Thrf78dMBH+4GkXSodXC5iliQTepWFQxQ0hHSxndP3UkxVLQdi426jsceG4bXjkmh+cv3q6ue3e/hAU5BZmAzyT/NOGrC92FYlqTYfqNKv+RqVZ rsa-key-20240327
# DO NOT EDIT - This file is being maintained by Chef - use authorized_keys2 instead
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAyBrnrkjzAJqXtRP0MFKlc3v4fTnrRzzebIFH8YpFRCaLKpIXWVbg5BqXuxHB/vqf/1Gknycb7bgLPbhWr+b50D+nnodiJ35HPqrQVLG6nsqxnbbVXO1IR7KsctL+Wr3GW5pBeWct9GAALn8ACAR8zZ/4V6qXDgUvh0inefcqpks1YgdPdyAGLMFy7hzI5lY8kGh58kVPXMpyJLVnGX0yUjrip9IkPrGBvMDiGDiPwLOfKGDR0s1An1GK2i4k2rPxkZzdQSbqZXaaCw3MNJkDvwSmQNQp4Rprfy5BqptwJg4PLnGGePfYbzsqYA0/Pq4ccO+NPCDxZxb2XuVjgXEg8Q== matt@horntail.openstreetmap.org
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDntpfnmWsP/9nh3JvT/AuNz3t4azrH54vKLrdtovYQ14QC66GA9EyAJel2eamyhevHQw5JU3Ic6H0ycXZus6QNn5vZKBn72/HXc/mvfRO2F5PvWVVF5LROoe1YBmYJugqpRwFekt9pIs49bbu3lZolnmmVT/uQP3sTFgErc/eqBtzgB+0OYijddQl3otzOZaZh1o4YaUvyutVb8ND3D1xgPxavWKW8B3BTDLF/Lr0wyh+CTWc1LtXVifIWpe9Muv+l+iww8AScyryLdMfcrUY+k76HwmkLbNV01hWMbfnB+4KoshFHnpmFN/Q4maoEXQpwP1II3iEKVs6QWFc4dImREtpiUJm5XeznlmfBuMac2gZPyPqSQPoUmxDTV7+umbcpw5IMGKFom6GJJJN2Az40TqNoQBAwnrJrmxzvLU8POpfYdZZfPLUB8l9nELGvIMhbRTBVpq6t99AxqvHlk3hc6yPTBFfltiBDB62QyOIEggbecnMaD1VvAkrthRITNJ9h0zdvrXM+X0pMo1QM8dBqRvrbBD7fr3gy2Oo+/XMsxf6Q8Fd7iu8oU8HYCwDexqZ8y9Nb54dOglWzSEPsTBAWf6PtBtZaXZ/VnNy3zjnJuOA99STQmqH5OPCY0eg6yRE6TILj9J4wWAXytXL9lF5YAW8JIT4+8pa4WhJoUGQz1w== zerebubuth@gmail.com
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef - use authorized_keys2 instead
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCmMyloQ+2+9Din4JPv11cu8EHgHREz3zljaxUDcU/zh2XoZIZn5jm9+qev+ga2ewX2gS8HflIIY5LG3sHCxhzUAvv5vFUha1qZVOA6CIi4WEqJfNkkyBuPFwYQDFwMgxQV/tOIAc/94lJ1DT/BrfJmeayh08OKgEpLLFTUDdlSA79sbQoT4JwTQM46H1s6r1adYjjZmz6vdyJ2yq3ODGWz356ad7hCch4AzK79MVkitaY2v17Zy+gKLkT75G1Fy4J0wBsDszNZHbNO95Exyqld4L4AvTGsz6JHglceMb/r7ma/Od0T+VT5TI5cQwZUqXOEOWRf2VptYQ7RrgSPKRq7 mikel_maron
--- /dev/null
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEVkoOPte6R6jN5w7yny+YLtoZGl/XLQL2aSjhgyNHrh matt@HEX
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef - use authorized_keys2 instead
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8FAjmvszUAHdZROboaVvTDniabLELeMe1WXHL55XelxAN3kZEmXLNbCXzLuYYQ5ASgrSVC5jX52bvPPJXeCR1NJXEfYNPyxfioMfAF298yNNap7Hkt2fmpjDleOJYK2gvJ7mHJjsTodno4j1Nm8pkr60r3n3ecYV9dMSk2ee37heYEZK9/Swcn8m79fCR0SBZ3JdsKeC+uMZxz9BXNF3COwgyO8C+/8+gwPGpqOMjQMLpHmuefGxGAINAV6CBes9N9g0ky8OiGjg1XQq9kMp+bihcAT8UKqc2+v9uH73eK9ZL3FYTcJwNO1IWofoU/eUT6hcrWnahPcVW5O5NBgRZ github
--- /dev/null
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCYxvvG3WcrofBviPhEhKuEBiej3WcLMEhYloJB0pOGF1DaK8kD6QRlH4mZaNmm4mZCQIUv2KfgxDyPmp8byGZniVQzx74dlFDozFY+q9beokQA/f5RjtWs2G8gO+V4UdNXxo9q3cvfjiK9eXtjLjYyMkwb8n6Y3jrpt7CDflb7Pa+yJF9C1ugPooa739YNw5M8qPWdP1QVK8M7zZTeUbGh1xWReGCwcKFNDtoOSyj1XXkKSvfGd+spKqfwKOHOqVXQYNtSm+nnIuGilLp8caFa3lOvcGnlXgSKExeiMq/zG7vlvierkuwz00yOxF6h6BgjLztLCsknt3mD92vhUqQz
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef - use authorized_keys2 instead
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCZmRTAN92TeqR9iIFsPFGmNdC7fGoH112eoY3D4JskfnezgdF+knA5qRf62VGnoa3oHfDZKGNaMexLZmyFLycyqFUln+TjzUpBLO3Ni7GykmIoxpTvzbs7iCtY9YChUUHz4qq7LP9W7QBRYYhgGMfa8IZUqTE3ogAG8uyKl+jn20PyVkkQabwePfCEm6WhcqKWA86u6R7SuE3O4YJsXIq9uaUZJVBomg+ORNcD90UcyTGzJ8hlqk9RBPvc4q2eTN3A9+/j/CDxiKAUFIqFeZ3nCZ/YFcS6Cxzl5+q4+NfFWe2zgFdw3YTWIdLsarMLJm55E9LHKhCedjel4P1tjqVr rtnf
# Keep tramp happy
if [[ "$TERM" = "dumb" ]]
then
+ unsetopt PROMPT_SP
+ unsetopt PROMPT_CR
unsetopt ZLE
fi
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef - use authorized_keys2 instead
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMnMNgIczCZtRuvd75FWGaTFD4xZSQ+EWAlR+CcMWDXM slack-key
default[:apache][:buffered_logs] = true
-default[:apache][:reqtimeout] = false
+default[:apache][:evasive][:enable] = true
+default[:apache][:evasive][:hash_table_size] = 65536
+# page_count is misnomer as it can match backends in some cases
+default[:apache][:evasive][:page_count] = 150
+default[:apache][:evasive][:site_count] = 250
+default[:apache][:evasive][:page_interval] = 1
+default[:apache][:evasive][:site_interval] = 1
+default[:apache][:evasive][:blocking_period] = 60
version "1.0.0"
supports "ubuntu"
-depends "munin"
+depends "fail2ban"
depends "prometheus"
depends "ssl"
+depends "systemd"
# limitations under the License.
#
-include_recipe "munin"
+include_recipe "fail2ban"
include_recipe "prometheus"
include_recipe "ssl"
mode "644"
end
-service "apache2" do
- action [:enable, :start]
- retries 2
- retry_delay 10
- supports :status => true, :restart => true, :reload => true
+systemd_service "apache2" do
+ dropin "chef"
+ memory_high "50%"
+ memory_max "75%"
+ notifies :restart, "service[apache2]"
end
apache_module "info" do
variables :hosts => admins["hosts"]
end
-apache_module "deflate" do
- conf "deflate.conf.erb"
-end
-
-if node[:apache][:reqtimeout]
- apache_module "reqtimeout" do
- action [:enable]
+if node[:apache][:evasive][:enable]
+ apache_module "evasive" do
+ conf "evasive.conf.erb"
end
else
- apache_module "reqtimeout" do
- action [:disable]
+ apache_module "evasive" do
+ action :disable
end
end
+apache_module "brotli" do
+ conf "brotli.conf.erb"
+end
+
+apache_module "deflate" do
+ conf "deflate.conf.erb"
+end
+
apache_module "headers"
apache_module "ssl"
template "ssl.erb"
end
-munin_plugin "apache_accesses"
-munin_plugin "apache_processes"
-munin_plugin "apache_volume"
+# Apache should only be started after modules enabled
+service "apache2" do
+ action [:enable, :start]
+ retries 2
+ retry_delay 10
+ supports :status => true, :restart => true, :reload => true
+end
+
+fail2ban_filter "apache-forbidden" do
+ action :delete
+end
+
+fail2ban_jail "apache-forbidden" do
+ action :delete
+end
+
+fail2ban_filter "apache-evasive" do
+ failregex ": Blacklisting address <ADDR>: possible DoS attack\.$"
+end
+
+fail2ban_jail "apache-evasive" do
+ filter "apache-evasive"
+ backend "systemd"
+ journalmatch "_SYSTEMD_UNIT=apache2.service SYSLOG_IDENTIFIER=mod_evasive"
+ ports [80, 443]
+ findtime "10m"
+ maxretry 3
+end
+
+template "/var/lib/prometheus/node-exporter/apache.prom" do
+ source "apache.prom.erb"
+ owner "root"
+ group "root"
+ mode "644"
+end
prometheus_exporter "apache" do
port 9117
- listen_switch "telemetry.address"
options "--scrape_uri=http://localhost/server-status?auto"
end
--- /dev/null
+# HELP apache_server_limit Value of ServerLimit directive
+# TYPE apache_server_limit gauge
+<% if node[:apache][:mpm] == "prefork" -%>
+apache_server_limit{} <%= node[:apache][:prefork][:server_limit] || 256 %>
+<% elsif node[:apache][:mpm] == "worker" -%>
+apache_server_limit{} <%= node[:apache][:worker][:server_limit] || 16 %>
+<% elsif node[:apache][:mpm] == "event" -%>
+apache_server_limit{} <%= node[:apache][:event][:server_limit] || 16 %>
+<% end -%>
+# HELP apache_threads_per_child Value of ThreadsPerChild directive
+# TYPE apache_threads_per_child gauge
+<% if node[:apache][:mpm] == "prefork" -%>
+apache_threads_per_child{} 1
+<% elsif node[:apache][:mpm] == "worker" -%>
+apache_threads_per_child{} <%= node[:apache][:worker][:threads_per_child] || 25 %>
+<% elsif node[:apache][:mpm] == "event" -%>
+apache_threads_per_child{} <%= node[:apache][:event][:threads_per_child] || 25 %>
+<% end -%>
+# HELP apache_async_request_worker_factor Value of AsyncRequestWorkerFactor directive
+# TYPE apache_async_request_worker_factor gauge
+<% if node[:apache][:mpm] == "prefork" -%>
+apache_async_request_worker_factor{} 0
+<% elsif node[:apache][:mpm] == "worker" -%>
+apache_async_request_worker_factor{} 0
+<% elsif node[:apache][:mpm] == "event" -%>
+apache_async_request_worker_factor{} <%= node[:apache][:event][:async_request_worker_factor] || 2 %>
+<% end -%>
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+<IfModule mod_brotli.c>
+ <IfModule mod_filter.c>
+ AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/xml text/css text/javascript
+ AddOutputFilterByType BROTLI_COMPRESS application/x-javascript application/javascript application/ecmascript
+ AddOutputFilterByType BROTLI_COMPRESS application/rss+xml
+ AddOutputFilterByType BROTLI_COMPRESS application/wasm
+ AddOutputFilterByType BROTLI_COMPRESS application/xml
+ AddOutputFilterByType BROTLI_COMPRESS image/svg+xml
+ </IfModule>
+</IfModule>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
# DO NOT EDIT - This file is being maintained by Chef
<IfModule mod_deflate.c>
- <IfModule mod_filter.c>
- # these are known to be safe with MSIE 6
- AddOutputFilterByType DEFLATE text/html text/plain text/xml
-
- # everything else may cause problems with MSIE 6
- AddOutputFilterByType DEFLATE text/css
- AddOutputFilterByType DEFLATE application/x-javascript application/javascript application/ecmascript
- AddOutputFilterByType DEFLATE application/rss+xml
- AddOutputFilterByType DEFLATE application/xml
- AddOutputFilterByType DEFLATE image/svg+xml
- </IfModule>
+ <IfModule mod_filter.c>
+ AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript
+ AddOutputFilterByType DEFLATE application/x-javascript application/javascript application/ecmascript
+ AddOutputFilterByType DEFLATE application/rss+xml
+ AddOutputFilterByType DEFLATE application/wasm
+ AddOutputFilterByType DEFLATE application/xml
+ AddOutputFilterByType DEFLATE image/svg+xml
+ </IfModule>
</IfModule>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+<IfModule mod_evasive20.c>
+ DOSHashTableSize <%= node[:apache][:evasive][:hash_table_size] %>
+ DOSPageCount <%= node[:apache][:evasive][:page_count] %>
+ DOSSiteCount <%= node[:apache][:evasive][:site_count] %>
+ DOSPageInterval <%= node[:apache][:evasive][:page_interval] %>
+ DOSSiteInterval <%= node[:apache][:evasive][:site_interval] %>
+ DOSBlockingPeriod <%= node[:apache][:evasive][:blocking_period] %>
+</IfModule>
# Configure logging
BufferedLogs <%= node[:apache][:buffered_logs] ? "On" : "Off" %>
+
+# Define an extended log format that includes request time and SSL details
+LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" %Dus %{SSL_PROTOCOL}x %{SSL_CIPHER}x" combined_extended
<Location /server-info>
SetHandler server-info
-<% node.ipaddresses do |address| -%>
+<% node.ipaddresses.sort.each do |address| -%>
Require ip <%= address %>
<% end -%>
Require ip 127.0.1.1
SSLStaplingCache shmcb:${APACHE_RUN_DIR}/ssl_ocspcache(512000)
Header always set Strict-Transport-Security "<%= node[:ssl][:strict_transport_security] %>" "expr=%{HTTPS} == 'on'"
-<% if node[:ssl][:ct_report_uri] -%>
-Header always set Expect-CT "max-age=0, report-uri=\"<%= node[:ssl][:ct_report_uri] %>\"" "expr=%{HTTPS} == 'on'"
-<% else -%>
-Header always set Expect-CT "max-age=0" "expr=%{HTTPS} == 'on'"
-<% end -%>
<Location /server-status>
SetHandler server-status
-<% node.ipaddresses do |address| -%>
+<% node.ipaddresses.sort.each do |address| -%>
Require ip <%= address %>
<% end -%>
Require ip 127.0.1.1
-default[:apt][:sources] = [ "openstreetmap" ]
default[:apt][:unattended_upgrades][:enable] = true
default[:apt][:unattended_upgrades][:remove_unused_dependencies] = true
apt
apt-transport-https
gnupg
- update-notifier-common
]
+package "update-notifier-common" if platform?("ubuntu")
+
file "/etc/motd.tail" do
action :delete
end
-template "/etc/apt/preferences.d/99-chef" do
- source "preferences.erb"
- owner "root"
- group "root"
- mode "644"
+# FIXME: cleanup old package pin method for cciss-vol-status
+file "/etc/apt/preferences.d/99-chef" do
+ action :delete
+end
+
+apt_preference "cciss-vol-status" do
+ pin "origin *.ubuntu.com"
+ pin_priority "1100"
end
apt_update "/etc/apt/sources.list" do
action :nothing
end
-archive_host = if node[:country]
- "#{node[:country]}.archive.ubuntu.com"
- else
- "archive.ubuntu.com"
- end
+if platform?("debian")
+ archive_host = "deb.debian.org"
+ archive_security_host = archive_host
+ archive_distro = "debian"
+ archive_security_distro = "debian-security"
+ archive_suites = %w[main updates backports security]
+ archive_components = %w[main contrib non-free non-free-firmware]
+elsif intel?
+ archive_host = if node[:country]
+ "#{node[:country]}.archive.ubuntu.com"
+ else
+ "archive.ubuntu.com"
+ end
+ archive_security_host = "security.ubuntu.com"
+ archive_distro = "ubuntu"
+ archive_security_distro = archive_distro
+ archive_suites = %w[main updates backports security]
+ archive_components = %w[main restricted universe multiverse]
+else
+ archive_host = "ports.ubuntu.com"
+ archive_security_host = archive_host
+ archive_distro = "ubuntu-ports"
+ archive_security_distro = archive_distro
+ archive_suites = %w[main updates backports security]
+ archive_components = %w[main restricted universe multiverse]
+end
template "/etc/apt/sources.list" do
source "sources.list.erb"
owner "root"
group "root"
mode "644"
- variables :archive_host => archive_host, :codename => node[:lsb][:codename]
+ variables :archive_host => archive_host,
+ :archive_security_host => archive_security_host,
+ :archive_distro => archive_distro,
+ :archive_security_distro => archive_security_distro,
+ :archive_suites => archive_suites,
+ :archive_components => archive_components,
+ :codename => node[:lsb][:codename]
notifies :update, "apt_update[/etc/apt/sources.list]", :immediately
end
-repository_actions = Hash.new do |_, repository|
- node[:apt][:sources].include?(repository) ? :add : :remove
-end
-
-apt_repository "brightbox-ruby-ng" do
- action repository_actions["brightbox-ruby-ng"]
- uri "ppa:brightbox/ruby-ng"
-end
-
-apt_repository "ubuntugis-stable" do
- action repository_actions["ubuntugis-stable"]
- uri "ppa:ubuntugis/ppa"
-end
-
-apt_repository "ubuntugis-unstable" do
- action repository_actions["ubuntugis-unstable"]
- uri "ppa:ubuntugis/ubuntugis-unstable"
-end
-
-apt_repository "git-core" do
- action repository_actions["git-core"]
- uri "ppa:git-core/ppa"
-end
-
-apt_repository "maxmind" do
- action repository_actions["maxmind"]
- uri "ppa:maxmind/ppa"
-end
-
apt_repository "openstreetmap" do
- action repository_actions["openstreetmap"]
uri "ppa:osmadmins/ppa"
-end
-
-apt_repository "squid2" do
- action repository_actions["squid2"]
- uri "ppa:osmadmins/squid2"
-end
-
-apt_repository "squid3" do
- action repository_actions["squid3"]
- uri "ppa:osmadmins/squid3"
-end
-
-apt_repository "squid4" do
- action repository_actions["squid4"]
- uri "ppa:osmadmins/squid4"
-end
-
-apt_repository "management-component-pack" do
- action repository_actions["management-component-pack"]
- uri "https://downloads.linux.hpe.com/SDR/repo/mcp"
- distribution "bionic/current-gen9"
- components ["non-free"]
- key "C208ADDE26C2B797"
-end
-
-apt_repository "hwraid" do
- action repository_actions["hwraid"]
- uri "https://hwraid.le-vert.net/ubuntu"
- distribution "precise"
- components ["main"]
- key "6005210E23B3D3B4"
-end
-
-apt_repository "nginx" do
- action repository_actions["nginx"]
- arch "amd64"
- uri "https://nginx.org/packages/ubuntu"
- components ["nginx"]
- key "ABF5BD827BD9BF62"
-end
-
-apt_repository "elasticsearch5.x" do
- action repository_actions["elasticsearch5.x"]
- uri "https://artifacts.elastic.co/packages/5.x/apt"
- distribution "stable"
- components ["main"]
- key "D27D666CD88E42B4"
-end
-
-apt_repository "elasticsearch6.x" do
- action repository_actions["elasticsearch6.x"]
- uri "https://artifacts.elastic.co/packages/6.x/apt"
- distribution "stable"
- components ["main"]
- key "D27D666CD88E42B4"
-end
-
-apt_repository "passenger" do
- action repository_actions["passenger"]
- uri "https://oss-binaries.phusionpassenger.com/apt/passenger"
- components ["main"]
- key "561F9B9CAC40B2F7"
-end
-
-apt_repository "postgresql" do
- action repository_actions["postgresql"]
- uri "https://apt.postgresql.org/pub/repos/apt"
- distribution "#{node[:lsb][:codename]}-pgdg"
- components ["main"]
- key "7FCC7D46ACCC4CF8"
-end
-
-apt_repository "mediawiki" do
- action repository_actions["mediawiki"]
- uri "https://releases.wikimedia.org/debian"
- distribution "jessie-mediawiki"
- components ["main"]
- key "AF380A3036A03444"
-end
-
-apt_repository "docker" do
- action repository_actions["docker"]
- uri "https://download.docker.com/linux/ubuntu"
- arch "amd64"
- components ["stable"]
- key "https://download.docker.com/linux/ubuntu/gpg"
-end
-
-apt_repository "grafana" do
- action repository_actions["grafana"]
- uri "https://packages.grafana.com/enterprise/deb"
- distribution "stable"
- components ["main"]
- key "https://packages.grafana.com/gpg.key"
-end
-
-apt_repository "timescaledb" do
- action repository_actions["timescaledb"]
- uri "ppa:timescale/timescaledb-ppa"
+ only_if { platform?("ubuntu") }
end
package "unattended-upgrades"
--- /dev/null
+#
+# Cookbook:: apt
+# Recipe:: docker
+#
+# Copyright:: 2022, Tom Hughes
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "apt"
+
+docker_platform = if platform?("debian")
+ "debian"
+ else
+ "ubuntu"
+ end
+
+docker_arch = if arm?
+ "arm64"
+ else
+ "amd64"
+ end
+
+apt_repository "docker" do
+ uri "https://download.docker.com/linux/#{docker_platform}"
+ arch docker_arch
+ components ["stable"]
+ key "https://download.docker.com/linux/#{docker_platform}/gpg"
+end
--- /dev/null
+#
+# Cookbook:: apt
+# Recipe:: elasticsearch6
+#
+# Copyright:: 2022, Tom Hughes
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "apt"
+
+apt_repository "elasticsearch6.x" do
+ uri "https://artifacts.elastic.co/packages/6.x/apt"
+ distribution "stable"
+ components ["main"]
+ key "D27D666CD88E42B4"
+end
--- /dev/null
+#
+# Cookbook:: apt
+# Recipe:: elasticsearch7
+#
+# Copyright:: 2022, Grant Slater
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "apt"
+
+apt_repository "elasticsearch7.x" do
+ uri "https://artifacts.elastic.co/packages/7.x/apt"
+ distribution "stable"
+ components ["main"]
+ key "D27D666CD88E42B4"
+end
+
+# Workaround for mediawiki 1.39.x which ONLY supports elasticsearch 7.10.2
+# elasticsearch 7.10.2 is the final Apache 2.0 licensed version of elasticsearch
+apt_preference "elasticsearch" do
+ pin "version 7.10.2"
+ pin_priority "1100"
+end
--- /dev/null
+#
+# Cookbook:: apt
+# Recipe:: elasticsearch8
+#
+# Copyright:: 2022, Tom Hughes
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "apt"
+
+apt_repository "elasticsearch8.x" do
+ uri "https://artifacts.elastic.co/packages/8.x/apt"
+ distribution "stable"
+ components ["main"]
+ key "D27D666CD88E42B4"
+end
--- /dev/null
+#
+# Cookbook:: apt
+# Recipe:: grafana
+#
+# Copyright:: 2022, Tom Hughes
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "apt"
+
+remote_file "/etc/apt/trusted.gpg.d/grafana.asc" do
+ source "https://packages.grafana.com/gpg.key"
+ owner "root"
+ group "root"
+ mode "644"
+end
+
+apt_repository "grafana" do
+ uri "https://packages.grafana.com/enterprise/deb"
+ distribution "stable"
+ components ["main"]
+end
--- /dev/null
+#
+# Cookbook:: apt
+# Recipe:: hwraid
+#
+# Copyright:: 2022, Tom Hughes
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "apt"
+
+platform_name = if platform?("debian")
+ "debian"
+ else
+ "ubuntu"
+ end
+
+distribution_name = if platform?("debian")
+ "buster"
+ else
+ "precise"
+ end
+
+apt_repository "hwraid" do
+ uri "https://hwraid.le-vert.net/#{platform_name}"
+ distribution distribution_name
+ components ["main"]
+ key "6005210E23B3D3B4"
+end
--- /dev/null
+#
+# Cookbook:: apt
+# Recipe:: management-component-pack
+#
+# Copyright:: 2022, Tom Hughes
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "apt"
+
+apt_repository "management-component-pack" do
+ action :remove
+end
+
+if platform?("debian")
+ apt_repository "mcp" do
+ uri "https://downloads.linux.hpe.com/SDR/repo/mcp"
+ distribution "#{node[:lsb][:codename]}/current"
+ components ["non-free"]
+ key "C208ADDE26C2B797"
+ end
+elsif platform?("ubuntu")
+ if node[:dmi][:system][:product_name].end_with?("Gen10")
+ apt_repository "mcp-jammy" do
+ uri "https://downloads.linux.hpe.com/SDR/repo/mcp"
+ distribution "jammy/current"
+ components ["non-free"]
+ key "C208ADDE26C2B797"
+ end
+
+ apt_repository "mcp-focal-gen10" do
+ uri "https://downloads.linux.hpe.com/SDR/repo/mcp"
+ distribution "focal/current-gen10"
+ components ["non-free"]
+ key "C208ADDE26C2B797"
+ end
+ else
+ apt_repository "mcp-bionic-gen9" do
+ uri "https://downloads.linux.hpe.com/SDR/repo/mcp"
+ distribution "bionic/current-gen9"
+ components ["non-free"]
+ key "C208ADDE26C2B797"
+ end
+ end
+end
--- /dev/null
+#
+# Cookbook:: apt
+# Recipe:: maxmind
+#
+# Copyright:: 2022, Tom Hughes
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "apt"
+
+apt_repository "maxmind" do
+ uri "ppa:maxmind/ppa"
+ only_if { platform?("ubuntu") }
+end
--- /dev/null
+#
+# Cookbook:: apt
+# Recipe:: nginx
+#
+# Copyright:: 2022, Tom Hughes
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "apt"
+
+platform_name = if platform?("debian")
+ "debian"
+ else
+ "ubuntu"
+ end
+
+apt_repository "nginx" do
+ arch "amd64"
+ uri "https://nginx.org/packages/#{platform_name}"
+ components ["nginx"]
+ key "ABF5BD827BD9BF62"
+end
--- /dev/null
+#
+# Cookbook:: apt
+# Recipe:: nodesource
+#
+# Copyright:: 2022, Tom Hughes
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "apt"
+
+apt_repository "nodesource" do
+ uri "https://deb.nodesource.com/node_20.x"
+ distribution "nodistro"
+ components ["main"]
+ key "https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key"
+end
--- /dev/null
+#
+# Cookbook:: apt
+# Recipe:: passenger
+#
+# Copyright:: 2022, Tom Hughes
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "apt"
+
+apt_repository "passenger" do
+ uri "https://oss-binaries.phusionpassenger.com/apt/passenger"
+ components ["main"]
+ key "561F9B9CAC40B2F7"
+end
--- /dev/null
+#
+# Cookbook:: apt
+# Recipe:: postgresql
+#
+# Copyright:: 2022, Tom Hughes
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "apt"
+
+apt_repository "postgresql" do
+ uri "https://apt.postgresql.org/pub/repos/apt"
+ distribution "#{node[:lsb][:codename]}-pgdg"
+ components ["main"]
+ key "7FCC7D46ACCC4CF8"
+end
--- /dev/null
+#
+# Cookbook:: apt
+# Recipe:: yarn
+#
+# Copyright:: 2022, Tom Hughes
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "apt"
+
+apt_repository "yarn" do
+ uri "https://dl.yarnpkg.com/debian"
+ distribution "stable"
+ components ["main"]
+ key "1646B01B86E50310"
+end
// Don't install recommended packages as we don't want to get
// new postgres versions automatically
APT::Install-Recommends "false";
+
+// Briefly wait for lock on dpkg/apt
+// to avoid concurrent issues with unattended-upgrades and apt daily
+DPkg::lock::timeout 90;
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-Package: cciss-vol-status
-Pin: origin "*.ubuntu.com"
-Pin-Priority: 1100
# DO NOT EDIT - This file is being maintained by Chef
+<% if @archive_suites.include?("main") -%>
-deb http://<%= @archive_host %>/ubuntu/ <%= @codename %> main restricted
-# deb-src http://<%= @archive_host %>/ubuntu/ <%= @codename %> main restricted
+deb http://<%= @archive_host %>/<%= @archive_distro %>/ <%= @codename %> <%= @archive_components.join(" ") %>
+# deb-src http://<%= @archive_host %>/<%= @archive_distro %>/ <%= @codename %> <%= @archive_components.join(" ") %>
+<% end -%>
+<% if @archive_suites.include?("updates") -%>
-## Major bug fix updates produced after the final release of the
-## distribution.
-deb http://<%= @archive_host %>/ubuntu/ <%= @codename %>-updates main restricted
-# deb-src http://<%= @archive_host %>/ubuntu/ <%= @codename %>-updates main restricted
+deb http://<%= @archive_host %>/<%= @archive_distro %>/ <%= @codename %>-updates <%= @archive_components.join(" ") %>
+# deb-src http://<%= @archive_host %>/<%= @archive_distro %>/ <%= @codename %>-updates <%= @archive_components.join(" ") %>
+<% end -%>
+<% if @archive_suites.include?("backports") -%>
-## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
-## team. Also, please note that software in universe WILL NOT receive any
-## review or updates from the Ubuntu security team.
-deb http://<%= @archive_host %>/ubuntu/ <%= @codename %> universe
-# deb-src http://<%= @archive_host %>/ubuntu/ <%= @codename %> universe
-deb http://<%= @archive_host %>/ubuntu/ <%= @codename %>-updates universe
-# deb-src http://<%= @archive_host %>/ubuntu/ <%= @codename %>-updates universe
+deb http://<%= @archive_host %>/<%= @archive_distro %>/ <%= @codename %>-backports <%= @archive_components.join(" ") %>
+# deb-src http://<%= @archive_host %>/<%= @archive_distro %>/ <%= @codename %>-backports <%= @archive_components.join(" ") %>
+<% end -%>
+<% if @archive_suites.include?("security") -%>
-## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
-## team, and may not be under a free licence. Please satisfy yourself as to
-## your rights to use the software. Also, please note that software in
-## multiverse WILL NOT receive any review or updates from the Ubuntu
-## security team.
-deb http://<%= @archive_host %>/ubuntu/ <%= @codename %> multiverse
-# deb-src http://<%= @archive_host %>/ubuntu/ <%= @codename %> multiverse
-deb http://<%= @archive_host %>/ubuntu/ <%= @codename %>-updates multiverse
-# deb-src http://<%= @archive_host %>/ubuntu/ <%= @codename %>-updates multiverse
-
-## N.B. software from this repository may not have been tested as
-## extensively as that contained in the main release, although it includes
-## newer versions of some applications which may provide useful features.
-## Also, please note that software in backports WILL NOT receive any review
-## or updates from the Ubuntu security team.
-deb http://<%= @archive_host %>/ubuntu/ <%= @codename %>-backports main restricted universe multiverse
-# deb-src http://<%= @archive_host %>/ubuntu/ <%= @codename %>-backports main restricted universe multiverse
-
-## Uncomment the following two lines to add software from Canonical's
-## 'partner' repository.
-## This software is not part of Ubuntu, but is offered by Canonical and the
-## respective vendors as a service to Ubuntu users.
-# deb http://archive.canonical.com/ubuntu <%= @codename %> partner
-# deb-src http://archive.canonical.com/ubuntu <%= @codename %> partner
-
-deb http://security.ubuntu.com/ubuntu/ <%= @codename %>-security main restricted
-# deb-src http://security.ubuntu.com/ubuntu/ <%= @codename %>-security main restricted
-deb http://security.ubuntu.com/ubuntu/ <%= @codename %>-security universe
-# deb-src http://security.ubuntu.com/ubuntu/ <%= @codename %>-security universe
-deb http://security.ubuntu.com/ubuntu/ <%= @codename %>-security multiverse
-# deb-src http://security.ubuntu.com/ubuntu/ <%= @codename %>-security multiverse
+deb http://<%= @archive_security_host %>/<%= @archive_security_distro %>/ <%= @codename %>-security <%= @archive_components.join(" ") %>
+# deb-src http://<%= @archive_security_host %>/<%= @archive_security_distro %>/ <%= @codename %>-security <%= @archive_components.join(" ") %>
+<% end -%>
--- /dev/null
+# awscli Cookbook
+
+This cookbook installs and configures awscli
--- /dev/null
+# Set the default awscli version
+default[:awscli][:version] = "latest"
-name "nfs"
+name "awscli"
maintainer "OpenStreetMap Administrators"
maintainer_email "admins@openstreetmap.org"
license "Apache-2.0"
-description "Installs and configures nfs"
+description "Installs and configures awscli"
version "1.0.0"
+supports "debian"
supports "ubuntu"
--- /dev/null
+#
+# Cookbook:: awscli
+# Recipe:: default
+#
+# Copyright:: 2023, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+cache_dir = Chef::Config[:file_cache_path]
+
+# Determine architecture of system for the AWS CLI download
+awscli_arch = if arm?
+ "aarch64"
+ else
+ "x86_64"
+ end
+
+awscli_version_suffix = if node[:awscli][:version] == "latest"
+ "" # latest version does not have a suffix
+ else
+ "-#{node[:awscli][:version]}"
+ end
+
+awscli_zip = "awscliv2#{awscli_version_suffix}.zip"
+
+# Ensure unpack directory is removed
+directory "#{cache_dir}/awscli" do
+ action :delete
+ recursive true
+end
+
+# Remove any existing AWS CLI zip files, unless it's the one we're downloading
+Dir.glob("#{cache_dir}/awscliv2*.zip").each do |zip|
+ next if zip == "#{cache_dir}/#{awscli_zip}"
+
+ file zip do
+ action :delete
+ backup false
+ end
+end
+
+# Download the AWS CLI zip file
+remote_file "#{cache_dir}/#{awscli_zip}" do
+ source "https://awscli.amazonaws.com/awscli-exe-linux-#{awscli_arch}#{awscli_version_suffix}.zip"
+ owner "root"
+ group "root"
+ mode "644"
+ backup false
+ ignore_failure true
+end
+
+# Extract the AWS CLI zip file
+archive_file "#{cache_dir}/#{awscli_zip}" do
+ path "#{cache_dir}/#{awscli_zip}"
+ destination "#{cache_dir}/awscli"
+ strip_components 1
+ action :nothing
+ subscribes :extract, "remote_file[#{cache_dir}/#{awscli_zip}]", :immediately
+end
+
+# Find the version of the AWS CLI we just downloaded
+# Example version string: aws-cli/2.12.6 Python/3.11.4 Linux/5.15.49-linuxkit-pr exe/aarch64.ubuntu.22 prompt/off
+# Install CLI to path: /opt/awscli/v2/current/bin/aws
+ruby_block "install-awscli" do
+ block do
+ require "fileutils"
+ awscli_version_string = shell_out("#{cache_dir}/awscli/dist/aws", "--version")
+ awscli_version = awscli_version_string.stdout.split(" ").first.split("/").last
+ FileUtils.mkdir_p("/opt/awscli/v2/#{awscli_version}/bin/", :mode => 0755)
+ FileUtils.mv("#{cache_dir}/awscli/dist", "/opt/awscli/v2/#{awscli_version}/dist", :force => true)
+ FileUtils.ln_sf("/opt/awscli/v2/#{awscli_version}/dist/aws", "/opt/awscli/v2/#{awscli_version}/bin/aws")
+ FileUtils.ln_sf("/opt/awscli/v2/#{awscli_version}/dist/aws_completer", "/opt/awscli/v2/#{awscli_version}/bin/aws_completer")
+ FileUtils.rm("/opt/awscli/v2/current") if File.exist?("/opt/awscli/v2/current")
+ FileUtils.ln_sf("/opt/awscli/v2/#{awscli_version}", "/opt/awscli/v2/current")
+ end
+ action :nothing
+ subscribes :run, "archive_file[#{cache_dir}/#{awscli_zip}]", :immediately
+end
}
my $dates = join("|", @dates);
-my $match = qr/^${prefix}\d{4}-\d{2}-\d{2}\./;
-my $keep = qr/^${prefix}(?:${dates})\./;
+my $match = qr/^\Q${prefix}\E\d{4}-\d{2}-\d{2}\./;
+my $keep = qr/^\Q${prefix}\E(?:${dates})\./;
opendir(DIR, "$dir") || die "Can't open ${dir}: $!";
-while (my $file = readdir(DIR))
-{
-# print "Expiring $file\n" if $file =~ $match && $file !~ $keep;
- unlink("${dir}/${file}") if $file =~ $match && $file !~ $keep;
-}
+my @files = sort(grep(/$match/, readdir(DIR)));
closedir(DIR);
+pop @files;
+
+for my $file (@files)
+{
+# print "Expiring $file\n" if $file !~ $keep;
+ unlink("${dir}/${file}") if $file !~ $keep;
+}
+
exit 0;
sub Monday
package %w[
perl
libdate-calc-perl
+ awscli
]
directory "/store/backup" do
# DO NOT EDIT - This file is being maintained by Chef
-for prefix in chef-server chef-repository chef-git forum git lists munin osm-blog osm-donate osmf-crm osmf-ledgersmb wiki-wiki.osmfoundation.org osqa otrs prometheus sotm svn switch2osm trac wiki-board.osmfoundation.org wiki-dwg.osmfoundation.org wiki-mwg.osmfoundation.org wiki-wiki.openstreetmap.org
+for prefix in blogs chef-server chef-repository chef-git community forum git lists osm-blog osmf-crm osmf-ledgersmb wiki-wiki.osmfoundation.org osqa otrs prometheus sotm svn switch2osm trac wiki-board.osmfoundation.org wiki-dwg.osmfoundation.org wiki-mwg.osmfoundation.org wiki-wiki.openstreetmap.org
do
/usr/local/bin/expire-backups --days=3 --weeks=3 --months=3 /store/backup $prefix
done
+++ /dev/null
-default[:bind] = {}
# limitations under the License.
#
-include_recipe "networking"
-
-clients = search(:node, "roles:#{node[:bind][:clients]}")
-
-ipv4_clients = clients.collect do |client|
- client.ipaddresses(:family => :inet)
-end.flatten
-
-ipv6_clients = clients.collect do |client|
- client.ipaddresses(:family => :inet6)
-end.flatten
-
package "bind9"
-service_name = if node[:lsb][:release].to_f < 20.04
- "bind9"
- else
- "named"
- end
-
-service service_name do
+service "named" do
action [:enable, :start]
end
owner "root"
group "root"
mode "644"
- notifies :restart, "service[#{service_name}]"
+ notifies :restart, "service[named]"
end
template "/etc/bind/named.conf.options" do
owner "root"
group "root"
mode "644"
- variables :ipv4_clients => ipv4_clients, :ipv6_clients => ipv6_clients
- notifies :restart, "service[#{service_name}]"
+ notifies :restart, "service[named]"
end
template "/etc/bind/db.10" do
owner "root"
group "root"
mode "644"
- notifies :reload, "service[#{service_name}]"
+ notifies :reload, "service[named]"
end
firewall_rule "accept-dns-udp" do
action :accept
- source "net"
- dest "fw"
- proto "udp"
+ context :incoming
+ protocol :udp
dest_ports "domain"
- source_ports "-"
end
firewall_rule "accept-dns-tcp" do
action :accept
- source "net"
- dest "fw"
- proto "tcp:syn"
+ context :incoming
+ protocol :tcp
dest_ports "domain"
- source_ports "-"
end
$TTL 604800
@ IN SOA <%= node[:fdqn] %>. root.openstreetmap.org. (
- 2019040301 ; Serial
+ 2021092001 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
3.0.0 IN PTR ridley.ucl.openstreetmap.org.
4.0.0 IN PTR snap-02.ucl.openstreetmap.org.
-5.0.0 IN PTR norbert.ucl.openstreetmap.org.
-6.0.0 IN PTR urmel.ucl.openstreetmap.org.
-7.0.0 IN PTR faffy.ucl.openstreetmap.org.
-8.0.0 IN PTR zark.ucl.openstreetmap.org.
-9.0.0 IN PTR eustace.ucl.openstreetmap.org.
10.0.0 IN PTR eddie.ucl.openstreetmap.org.
-11.0.0 IN PTR draco.ucl.openstreetmap.org.
12.0.0 IN PTR sarel.ucl.openstreetmap.org.
13.0.0 IN PTR noquiklos.ucl.openstreetmap.org.
-14.0.0 IN PTR errol.ucl.openstreetmap.org.
15.0.0 IN PTR ysera.ucl.openstreetmap.org.
17.0.0 IN PTR clifford.ucl.openstreetmap.org.
-19.0.0 IN PTR grindtooth.ucl.openstreetmap.org.
20.0.0 IN PTR pummelzacken.ucl.openstreetmap.org.
-40.0.0 IN PTR tiamat-00.ucl.openstreetmap.org.
-41.0.0 IN PTR tiamat-01.ucl.openstreetmap.org.
-42.0.0 IN PTR tiamat-02.ucl.openstreetmap.org.
-43.0.0 IN PTR tiamat-03.ucl.openstreetmap.org.
-44.0.0 IN PTR tiamat-10.ucl.openstreetmap.org.
-45.0.0 IN PTR tiamat-11.ucl.openstreetmap.org.
-46.0.0 IN PTR tiamat-12.ucl.openstreetmap.org.
-47.0.0 IN PTR tiamat-13.ucl.openstreetmap.org.
-48.0.0 IN PTR tiamat-20.ucl.openstreetmap.org.
-49.0.0 IN PTR tiamat-21.ucl.openstreetmap.org.
-50.0.0 IN PTR tiamat-22.ucl.openstreetmap.org.
-51.0.0 IN PTR tiamat-23.ucl.openstreetmap.org.
3.1.0 IN PTR ridley.oob.openstreetmap.org.
4.1.0 IN PTR snap-02.oob.openstreetmap.org.
-5.1.0 IN PTR norbert.oob.openstreetmap.org.
-6.1.0 IN PTR urmel.oob.openstreetmap.org.
-8.1.0 IN PTR zark.oob.openstreetmap.org.
-9.1.0 IN PTR eustace.oob.openstreetmap.org.
10.1.0 IN PTR eddie.oob.openstreetmap.org.
-11.1.0 IN PTR draco.oob.openstreetmap.org.
12.1.0 IN PTR sarel.oob.openstreetmap.org.
13.1.0 IN PTR noquiklos.oob.openstreetmap.org.
-14.1.0 IN PTR errol.oob.openstreetmap.org.
15.1.0 IN PTR ysera.oob.openstreetmap.org.
17.1.0 IN PTR clifford.oob.openstreetmap.org.
-19.1.0 IN PTR grindtooth.oob.openstreetmap.org.
20.1.0 IN PTR pummelzacken.oob.openstreetmap.org.
-40.1.0 IN PTR tiamat-00.oob.openstreetmap.org.
-41.1.0 IN PTR tiamat-01.oob.openstreetmap.org.
-42.1.0 IN PTR tiamat-02.oob.openstreetmap.org.
-43.1.0 IN PTR tiamat-03.oob.openstreetmap.org.
-44.1.0 IN PTR tiamat-10.oob.openstreetmap.org.
-45.1.0 IN PTR tiamat-11.oob.openstreetmap.org.
-46.1.0 IN PTR tiamat-12.oob.openstreetmap.org.
-47.1.0 IN PTR tiamat-13.oob.openstreetmap.org.
-48.1.0 IN PTR tiamat-20.oob.openstreetmap.org.
-49.1.0 IN PTR tiamat-21.oob.openstreetmap.org.
-50.1.0 IN PTR tiamat-22.oob.openstreetmap.org.
-51.1.0 IN PTR tiamat-23.oob.openstreetmap.org.
-2.16.0 IN PTR orm.bm.openstreetmap.org.
-3.16.0 IN PTR shenron.bm.openstreetmap.org.
-
-20.32.0 IN PTR grisu.bm.openstreetmap.org.
-21.32.0 IN PTR spike-04.bm.openstreetmap.org.
-22.32.0 IN PTR spike-05.bm.openstreetmap.org.
-40.32.0 IN PTR katla.bm.openstreetmap.org.
-41.32.0 IN PTR thorn-04.bm.openstreetmap.org.
-42.32.0 IN PTR thorn-05.bm.openstreetmap.org.
-
-20.33.0 IN PTR grisu.oob.openstreetmap.org.
-21.33.0 IN PTR spike-04.oob.openstreetmap.org.
-22.33.0 IN PTR spike-05.oob.openstreetmap.org.
-40.33.0 IN PTR katla.oob.openstreetmap.org.
-41.33.0 IN PTR thorn-04.oob.openstreetmap.org.
-42.33.0 IN PTR thorn-05.oob.openstreetmap.org.
-
-3.48.0 IN PTR orm.ams.openstreetmap.org.
-4.48.0 IN PTR ouroboros.ams.openstreetmap.org.
-5.48.0 IN PTR ramoth.ams.openstreetmap.org.
-6.48.0 IN PTR spike-01.ams.openstreetmap.org.
-7.48.0 IN PTR spike-02.ams.openstreetmap.org.
-8.48.0 IN PTR spike-03.ams.openstreetmap.org.
+3.48.0 IN PTR faffy.ams.openstreetmap.org.
+4.48.0 IN PTR dribble.ams.openstreetmap.org.
+5.48.0 IN PTR vhagar.ams.openstreetmap.org.
9.48.0 IN PTR dulcy.ams.openstreetmap.org.
10.48.0 IN PTR ironbelly.ams.openstreetmap.org.
11.48.0 IN PTR spike-06.ams.openstreetmap.org.
13.48.0 IN PTR spike-08.ams.openstreetmap.org.
14.48.0 IN PTR tabaluga.ams.openstreetmap.org.
15.48.0 IN PTR odin.ams.openstreetmap.org.
-16.48.0 IN PTR lockheed.ams.openstreetmap.org.
+17.48.0 IN PTR norbert.ams.openstreetmap.org.
49.48.0 IN PTR snap-01.ams.openstreetmap.org.
50.48.0 IN PTR karm.ams.openstreetmap.org.
-52.48.0 IN PTR thorn-02.ams.openstreetmap.org.
-53.48.0 IN PTR thorn-03.ams.openstreetmap.org.
-100.48.0 IN PTR pdu1.openstreetmap.org.
-101.48.0 IN PTR pdu2.openstreetmap.org.
+100.48.0 IN PTR pdu1.ams.openstreetmap.org.
+101.48.0 IN PTR pdu2.ams.openstreetmap.org.
+102.48.0 IN PTR oob1.ams.openstreetmap.org.
-3.49.0 IN PTR orm.oob.openstreetmap.org.
-4.49.0 IN PTR ouroboros.oob.openstreetmap.org.
-5.49.0 IN PTR ramoth.oob.openstreetmap.org.
-6.49.0 IN PTR spike-01.oob.openstreetmap.org.
-7.49.0 IN PTR spike-02.oob.openstreetmap.org.
-8.49.0 IN PTR spike-03.oob.openstreetmap.org.
+3.49.0 IN PTR faffy.oob.openstreetmap.org.
9.49.0 IN PTR dulcy.oob.openstreetmap.org.
10.49.0 IN PTR ironbelly.oob.openstreetmap.org.
11.49.0 IN PTR spike-06.oob.openstreetmap.org.
13.49.0 IN PTR spike-08.oob.openstreetmap.org.
14.49.0 IN PTR tabaluga.oob.openstreetmap.org.
15.49.0 IN PTR odin.oob.openstreetmap.org.
-16.49.0 IN PTR lockheed.oob.openstreetmap.org.
+17.49.0 IN PTR norbert.oob.openstreetmap.org.
49.49.0 IN PTR snap-01.oob.openstreetmap.org.
50.49.0 IN PTR karm.oob.openstreetmap.org.
52.49.0 IN PTR thorn-02.oob.openstreetmap.org.
53.49.0 IN PTR thorn-03.oob.openstreetmap.org.
+
+2.64.0 IN PTR fafnir.dub.openstreetmap.org.
+3.64.0 IN PTR spike-01.dub.openstreetmap.org.
+4.64.0 IN PTR spike-02.dub.openstreetmap.org.
+5.64.0 IN PTR spike-03.dub.openstreetmap.org.
+6.64.0 IN PTR idris.dub.openstreetmap.org.
+7.64.0 IN PTR konqi.dub.openstreetmap.org.
+8.64.0 IN PTR naga.dub.openstreetmap.org.
+9.64.0 IN PTR culebre.dub.openstreetmap.org.
+10.64.0 IN PTR horntail.dub.openstreetmap.org.
+12.64.0 IN PTR jakelong.dub.openstreetmap.org.
+13.64.0 IN PTR longma.dub.openstreetmap.org.
+14.64.0 IN PTR smaug.dub.openstreetmap.org.
+15.64.0 IN PTR muirdris.dub.openstreetmap.org.
+16.64.0 IN PTR fume.dub.openstreetmap.org.
+17.64.0 IN PTR grisu.dub.openstreetmap.org.
+50.64.0 IN PTR snap-03.dub.openstreetmap.org.
+100.64.0 IN PTR pdu1.dub.openstreetmap.org.
+101.64.0 IN PTR pdu2.dub.openstreetmap.org.
+102.64.0 IN PTR oob1.dub.openstreetmap.org.
+
+2.65.0 IN PTR fafnir.oob.openstreetmap.org.
+3.65.0 IN PTR spike-01.oob.openstreetmap.org.
+4.65.0 IN PTR spike-02.oob.openstreetmap.org.
+5.65.0 IN PTR spike-03.oob.openstreetmap.org.
+6.65.0 IN PTR idris.oob.openstreetmap.org.
+7.65.0 IN PTR konqi.oob.openstreetmap.org.
+8.65.0 IN PTR naga.oob.openstreetmap.org.
+9.65.0 IN PTR culebre.oob.openstreetmap.org.
+10.65.0 IN PTR horntail.oob.openstreetmap.org.
+12.65.0 IN PTR jakelong.oob.openstreetmap.org.
+13.65.0 IN PTR longma.oob.openstreetmap.org.
+14.65.0 IN PTR smaug.oob.openstreetmap.org.
+15.65.0 IN PTR muirdris.oob.openstreetmap.org.
+50.65.0 IN PTR snap-03.oob.openstreetmap.org.
# DO NOT EDIT - This file is being maintained by Chef
-acl "osm" {
- 127.0.0.1/32;
-<% node.interfaces(:family => :inet).each do |interface| -%>
- <%= interface[:network] %>/<%= interface[:prefix] %>;
-<% end -%>
-<% @ipv4_clients.sort.each do |address| -%>
- <%= address %>/32;
-<% end -%>
-
- ::1/128;
-<% node.interfaces(:family => :inet6).each do |interface| -%>
- <%= interface[:network] %>/<%= interface[:prefix] %>;
-<% end -%>
-<% @ipv6_clients.sort.each do |address| -%>
- <%= address %>/128;
-<% end -%>
-};
-
options {
# Directory to use for any working files
directory "/var/cache/bind";
-<% if node[:bind][:forwarders] -%>
- # Forward any queries we can't answer
- forwarders {
-<% node[:bind][:forwarders].each do |forwarder| -%>
- <%= forwarder %>;
-<% end -%>
- };
-<% end -%>
-
# Only allow queries from our machines
- allow-query { osm; };
+ allow-query { localnets; };
# Don't allow transfers
allow-transfer { none; };
include_recipe "wordpress"
passwords = data_bag_item("blog", "passwords")
+wp2fa_encrypt_keys = data_bag_item("blog", "wp2fa_encrypt_keys")
directory "/srv/blog.openstreetmap.org" do
owner "wordpress"
wordpress_site "blog.openstreetmap.org" do
aliases ["blog.osm.org", "blog.openstreetmap.com",
"blog.openstreetmap.net", "blog.openstreetmaps.org",
- "blog.osmfoundation.org"]
+ "blog.osmfoundation.org",
+ "opengeodata.org", "www.opengeodata.org",
+ "old.opengeodata.org" # https://blog.openstreetmap.org/2010/02/25/old-opengeodata-posts-now-up-at-old-opengeodata-org/
+ ]
directory "/srv/blog.openstreetmap.org/wp"
database_name "osm-blog"
database_user "osm-blog-user"
database_password passwords["osm-blog-user"]
+ wp2fa_encrypt_key wp2fa_encrypt_keys["key"]
urls "/casts" => "/srv/blog.openstreetmap.org/casts",
"/images" => "/srv/blog.openstreetmap.org/images",
"/static" => "/srv/blog.openstreetmap.org/static"
wordpress_theme "blog.openstreetmap.org-osmblog-wp-theme" do
theme "osmblog-wp-theme"
site "blog.openstreetmap.org"
- repository "https://github.com/harry-wood/osmblog-wp-theme.git"
+ repository "https://github.com/osmfoundation/osmblog-wp-theme.git"
end
wordpress_plugin "blog.openstreetmap.org-google-analytics-for-wordpress" do
+ action :delete
plugin "google-analytics-for-wordpress"
site "blog.openstreetmap.org"
end
wordpress_plugin "blog.openstreetmap.org-google-sitemap-generator" do
+ action :delete
plugin "google-sitemap-generator"
site "blog.openstreetmap.org"
end
+# wordpress_plugin "blog.openstreetmap.org-www-xml-sitemap-generator-org" do
+# plugin "www-xml-sitemap-generator-org"
+# site "blog.openstreetmap.org"
+# end
+
wordpress_plugin "blog.openstreetmap.org-shareadraft" do
+ action :delete
plugin "shareadraft"
site "blog.openstreetmap.org"
end
+wordpress_plugin "blog.openstreetmap.org-public-post-preview" do
+ plugin "public-post-preview"
+ site "blog.openstreetmap.org"
+end
+
wordpress_plugin "blog.openstreetmap.org-sitepress-multilingual-cms" do
plugin "sitepress-multilingual-cms"
site "blog.openstreetmap.org"
repository "https://git.openstreetmap.org/private/sitepress-multilingual-cms.git"
- not_if { ENV["TEST_KITCHEN"] }
+ revision "master"
+ not_if { kitchen? }
end
wordpress_plugin "blog.openstreetmap.org-wordpress-importer" do
+ action :delete
plugin "wordpress-importer"
site "blog.openstreetmap.org"
end
git "/srv/blog.openstreetmap.org/casts" do
action :sync
repository "https://github.com/openstreetmap/opengeodata-podcasts.git"
+ revision "master"
depth 1
user "wordpress"
group "wordpress"
git "/srv/blog.openstreetmap.org/images" do
action :sync
repository "https://github.com/openstreetmap/opengeodata-images.git"
+ revision "master"
depth 1
user "wordpress"
group "wordpress"
git "/srv/blog.openstreetmap.org/static" do
action :sync
repository "https://github.com/openstreetmap/opengeodata-static.git"
+ revision "master"
depth 1
user "wordpress"
group "wordpress"
end
-ssl_certificate "opengeodata.org" do
- domains ["opengeodata.org", "www.opengeodata.org", "old.opengeodata.org"]
- notifies :reload, "service[apache2]"
-end
-
-apache_site "opengeodata.org" do
- template "opengeodata.erb"
- directory "/srv/opengeodata.org"
-end
-
template "/etc/cron.daily/blog-backup" do
source "backup.cron.erb"
owner "root"
--- /dev/null
+#
+# Cookbook:: blog
+# Recipe:: staging
+#
+# Copyright:: 2024, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "wordpress"
+
+passwords = data_bag_item("blog-staging", "passwords")
+wp2fa_encrypt_keys = data_bag_item("blog-staging", "wp2fa_encrypt_keys")
+
+directory "/srv/staging.blog.openstreetmap.org" do
+ owner "wordpress"
+ group "wordpress"
+ mode "755"
+end
+
+wordpress_site "staging.blog.openstreetmap.org" do
+ aliases ["staging.blog.osm.org", "staging.blog.openstreetmap.com",
+ "staging.blog.openstreetmap.net", "staging.blog.openstreetmaps.org",
+ "staging.blog.osmfoundation.org"
+ ]
+ directory "/srv/staging.blog.openstreetmap.org/wp"
+ database_name "osm-blog-staging"
+ database_user "osm-blog-staging-user"
+ database_password passwords["osm-blog-staging-user"]
+ wp2fa_encrypt_key wp2fa_encrypt_keys["key"]
+ urls "/casts" => "/srv/staging.blog.openstreetmap.org/casts",
+ "/images" => "/srv/staging.blog.openstreetmap.org/images",
+ "/static" => "/srv/staging.blog.openstreetmap.org/static"
+ fpm_prometheus_port 11401
+end
+
+wordpress_theme "staging.blog.openstreetmap.org-osmblog-wp-theme" do
+ theme "osmblog-wp-theme"
+ site "staging.blog.openstreetmap.org"
+ repository "https://github.com/osmfoundation/osmblog-wp-theme.git"
+end
+
+wordpress_plugin "staging.blog.openstreetmap.org-google-analytics-for-wordpress" do
+ action :delete
+ plugin "google-analytics-for-wordpress"
+ site "staging.blog.openstreetmap.org"
+end
+
+wordpress_plugin "staging.blog.openstreetmap.org-google-sitemap-generator" do
+ action :delete
+ plugin "google-sitemap-generator"
+ site "staging.blog.openstreetmap.org"
+end
+
+# wordpress_plugin "blog.openstreetmap.org-www-xml-sitemap-generator-org" do
+# plugin "www-xml-sitemap-generator-org"
+# site "staging.blog.openstreetmap.org"
+# end
+
+wordpress_plugin "staging.blog.openstreetmap.org-shareadraft" do
+ action :delete
+ plugin "shareadraft"
+ site "staging.blog.openstreetmap.org"
+end
+
+wordpress_plugin "staging.blog.openstreetmap.org-public-post-preview" do
+ plugin "public-post-preview"
+ site "staging.blog.openstreetmap.org"
+end
+
+wordpress_plugin "staging.blog.openstreetmap.org-sitepress-multilingual-cms" do
+ plugin "sitepress-multilingual-cms"
+ site "staging.blog.openstreetmap.org"
+ repository "https://git.openstreetmap.org/private/sitepress-multilingual-cms.git"
+ revision "master"
+ not_if { kitchen? }
+end
+
+wordpress_plugin "staging.blog.openstreetmap.org-wordpress-importer" do
+ action :delete
+ plugin "wordpress-importer"
+ site "staging.blog.openstreetmap.org"
+end
+
+wordpress_plugin "staging.blog.openstreetmap.org-wp-piwik" do
+ plugin "wp-piwik"
+ site "staging.blog.openstreetmap.org"
+end
+
+git "/srv/staging.blog.openstreetmap.org/casts" do
+ action :sync
+ repository "https://github.com/openstreetmap/opengeodata-podcasts.git"
+ revision "master"
+ depth 1
+ user "wordpress"
+ group "wordpress"
+end
+
+git "/srv/staging.blog.openstreetmap.org/images" do
+ action :sync
+ repository "https://github.com/openstreetmap/opengeodata-images.git"
+ revision "master"
+ depth 1
+ user "wordpress"
+ group "wordpress"
+end
+
+git "/srv/staging.blog.openstreetmap.org/static" do
+ action :sync
+ repository "https://github.com/openstreetmap/opengeodata-static.git"
+ revision "master"
+ depth 1
+ user "wordpress"
+ group "wordpress"
+end
+
+template "/etc/cron.daily/blog-staging-backup" do
+ source "backup-staging.cron.erb"
+ owner "root"
+ group "root"
+ mode "750"
+ variables :passwords => passwords
+end
--- /dev/null
+#!/bin/sh
+
+# DO NOT EDIT - This file is being maintained by Chef
+
+T=$(mktemp -d -t -p /var/tmp osm-blog-staging.XXXXXXXXXX)
+D=$(date +%Y-%m-%d)
+B=osm-blog-staging-$D.tar.gz
+
+mkdir $T/osm-blog-staging-$D
+echo '[mysqldump]' > $T/mysqldump.opts
+echo 'user=osm-blog-staging-user' >> $T/mysqldump.opts
+echo 'password=<%= @passwords["osm-blog-staging-user"] %>' >> $T/mysqldump.opts
+mysqldump --defaults-file=$T/mysqldump.opts --opt --no-tablespaces osm-blog-staging > $T/osm-blog-staging-$D/osm-blog-staging.sql
+ln -s /srv/staging.blog.openstreetmap.org $T/osm-blog-staging-$D/www
+
+export RSYNC_RSH="ssh -ax"
+
+nice tar --create --dereference --directory=$T --warning=no-file-changed osm-blog-staging-$D | nice gzip --rsyncable -9 > $T/$B
+nice rsync --preallocate --fuzzy $T/$B backup::backup
+
+rm -rf $T
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-<VirtualHost *:80>
- ServerName opengeodata.org
- ServerAlias www.opengeodata.org
- ServerAlias old.opengeodata.org # https://blog.openstreetmap.org/2010/02/25/old-opengeodata-posts-now-up-at-old-opengeodata-org/
-
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
- ErrorLog /var/log/apache2/<%= @name %>-error.log
-
- RewriteEngine on
- RewriteRule ^(.*/)index\.html$ https://blog.openstreetmap.org/$1 [R=permanent,L]
-
- RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
- RedirectPermanent / https://blog.openstreetmap.org/
-</VirtualHost>
-
-<VirtualHost *:443>
- ServerName opengeodata.org
- ServerAlias www.opengeodata.org
- ServerAlias old.opengeodata.org # https://blog.openstreetmap.org/2010/02/25/old-opengeodata-posts-now-up-at-old-opengeodata-org/
-
- ServerAdmin webmaster@openstreetmap.org
-
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/opengeodata.org.pem
- SSLCertificateKeyFile /etc/ssl/private/opengeodata.org.key
-
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
- ErrorLog /var/log/apache2/<%= @name %>-error.log
-
- RewriteEngine on
- RewriteRule ^(.*/)index\.html$ https://blog.openstreetmap.org/$1 [R=permanent,L]
-
- RedirectPermanent / https://blog.openstreetmap.org/
-</VirtualHost>
depends "accounts"
depends "apache"
depends "git"
+depends "ruby"
+depends "systemd"
include_recipe "accounts"
include_recipe "apache"
include_recipe "git"
-
-ruby_version = if node[:lsb][:release].to_f < 20.04
- "2.5"
- else
- "2.7"
- end
+include_recipe "ruby"
package %W[
- ruby#{ruby_version}
- ruby#{ruby_version}-dev
make
gcc
g++
libsqlite3-dev
+ sqlite3
]
-gem_package "bundler#{ruby_version}" do
- package_name "bundler"
- version "~> 2.1.4"
- gem_binary "gem#{ruby_version}"
- options "--format-executable"
-end
-
directory "/srv/blogs.openstreetmap.org" do
owner "blogs"
group "blogs"
depth 1
user "blogs"
group "blogs"
- notifies :run, "execute[/srv/blogs.openstreetmap.org/Gemfile]", :immediately
+ notifies :run, "bundle_install[/srv/blogs.openstreetmap.org]", :immediately
end
-execute "/srv/blogs.openstreetmap.org/Gemfile" do
+bundle_install "/srv/blogs.openstreetmap.org" do
action :nothing
- command "bundle#{ruby_version} install --deployment"
- cwd "/srv/blogs.openstreetmap.org"
+ options "--deployment"
user "blogs"
group "blogs"
- notifies :run, "execute[/srv/blogs.openstreetmap.org]", :immediately
+ notifies :run, "bundle_exec[/srv/blogs.openstreetmap.org]", :immediately
end
-execute "/srv/blogs.openstreetmap.org" do
+bundle_exec "/srv/blogs.openstreetmap.org" do
action :nothing
- command "bundle#{ruby_version} exec pluto build -t osm -o build"
- cwd "/srv/blogs.openstreetmap.org"
+ command "pluto build -t osm -o build"
user "blogs"
group "blogs"
end
owner "root"
group "root"
mode "0755"
- variables :ruby_version => ruby_version
end
-cron_d "blogs" do
- minute "*/30"
+systemd_service "blogs-update" do
+ description "Update blog aggregator"
+ exec_start "/usr/local/bin/blogs-update"
user "blogs"
- command "/usr/local/bin/blogs-update"
- mailto "admins@openstreetmap.org"
+ sandbox :enable_network => true
+ read_write_paths "/srv/blogs.openstreetmap.org"
+end
+
+systemd_timer "blogs-update" do
+ description "Update blog aggregator"
+ on_boot_sec "15m"
+ on_unit_inactive_sec "30m"
+end
+
+service "blogs-update.timer" do
+ action [:enable, :start]
+end
+
+template "/etc/cron.daily/blogs-backup" do
+ source "backup.cron.erb"
+ owner "root"
+ group "root"
+ mode "0755"
end
<% end -%>
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
RedirectPermanent / https://<%= @name %>/
SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
DocumentRoot <%= @directory %>
--- /dev/null
+#!/bin/sh
+
+# DO NOT EDIT - This file is being maintained by Chef
+
+T=$(mktemp -d -t -p /var/tmp blogs.XXXXXXXXXX)
+D=$(date +%Y-%m-%d)
+B=blogs-$D.tar.gz
+
+mkdir $T/blogs-$D
+sqlite3 /srv/blogs.openstreetmap.org/planet.db ".backup $T/blogs-$D/planet.db"
+
+export RSYNC_RSH="ssh -ax"
+
+nice tar --create --dereference --directory=$T blogs-$D | nice gzip --rsyncable -9 > $T/$B
+nice rsync --preallocate --fuzzy $T/$B backup::backup
+
+rm -rf $T
cd /srv/blogs.openstreetmap.org
-/usr/local/bin/bundle<%= @ruby_version %> exec pluto \
+<%= node[:ruby][:bundle] %> exec pluto \
--quieter \
--config=/srv/blogs.openstreetmap.org build \
--dbpath=/srv/blogs.openstreetmap.org \
-# Add the opscode APT source for chef
-default[:apt][:sources] = node[:apt][:sources] | ["opscode"]
-
# Set the default server version
-default[:chef][:server][:version] = "12.17.33"
+default[:chef][:server][:version] = "15.1.7"
# Set the default client version
-default[:chef][:client][:version] = "16.13.16"
+default[:chef][:client][:version] = "18.4.2"
--- /dev/null
+module OpenStreetMap
+ module Mixin
+ module CPU
+ def cpu_cores
+ [dig("cpu", "total").to_i, dig("cpu", "cores").to_i, 4].max
+ end
+ end
+ end
+end
+
+Chef::Node.include(OpenStreetMap::Mixin::CPU)
-class Chef
+module OpenStreetMap
module Mixin
module EditFile
def edit_file(file, &_block)
end
end
end
-
- class Recipe
- include Chef::Mixin::EditFile
- end
end
+
+Chef::DSL::Recipe.include(OpenStreetMap::Mixin::EditFile)
require "digest"
-class Chef
+module OpenStreetMap
module Mixin
module PersistentToken
def persistent_token(*args)
end
end
end
-
- class Recipe
- include Chef::Mixin::PersistentToken
- end
end
+
+Chef::DSL::Recipe.include(OpenStreetMap::Mixin::PersistentToken)
+++ /dev/null
-class Chef
- class Recipe
- def random_password(length)
- Array.new(length) do
- "!\#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~"[rand(91)].chr
- end.join
- end
- end
-end
class Subversion
extend Chef::Mixin::ShellOut
+ def shell_out!(*args, **options)
+ options = args.pop if options.empty? && args.last.is_a?(Hash)
+
+ super(*args, **options)
+ end
+
def sync_command
if current_repository_matches_target_repository?
c = scm :update, new_resource.svn_arguments, verbose, authentication, proxy, "-r#{revision_int}", new_resource.destination
Chef::Log.debug "#{new_resource} updated working copy #{new_resource.destination} to revision #{new_resource.revision}"
else
- c = scm :switch, new_resource.svn_arguments, verbose, authentication, proxy, "-r#{revision_int}", new_resource.repository, new_resource.destination
+ c = scm :switch, new_resource.svn_arguments, verbose, authentication, proxy, "-r#{revision_int}", "--ignore-ancestry", new_resource.repository, new_resource.destination
Chef::Log.debug "#{new_resource} updated working copy #{new_resource.destination} to #{new_resource.repository} revision #{new_resource.revision}"
end
c
def svn_info
command = scm(:info)
- shell_out!(command, run_options(:cwd => cwd, :returns => [0, 1])).stdout
+ shell_out!(command, **run_options(:cwd => cwd, :returns => [0, 1])).stdout
end
def revision_int
new_resource.revision
else
command = scm(:info, new_resource.repository, new_resource.svn_info_args, authentication, "-r#{new_resource.revision}")
- svn_info = shell_out!(command, run_options(:returns => [0, 1])).stdout
+ svn_info = shell_out!(command, **run_options(:returns => [0, 1])).stdout
extract_revision_info(svn_info)
end
depends "apt"
depends "git"
depends "ohai"
-depends "munin"
depends "systemd"
-gem "mail"
+gem "mail", "= 2.7.1"
cache_dir = Chef::Config[:file_cache_path]
chef_version = node[:chef][:client][:version]
-chef_package = "chef_#{chef_version}-1_amd64.deb"
+
+chef_platform = if platform?("debian")
+ "debian"
+ else
+ "ubuntu"
+ end
+
+chef_arch = if arm?
+ "arm64"
+ else
+ "amd64"
+ end
+
+os_release = if platform?("debian") && node[:lsb][:release].to_f > 11
+ 11
+ else
+ node[:lsb][:release]
+ end
+
+# Chef is currently not available for Debian 11 on arm64.
+if chef_platform == "debian" && os_release == 11 && chef_arch == "arm64"
+ chef_platform = "ubuntu"
+ os_release = "22.04"
+end
+
+chef_package = "chef_#{chef_version}-1_#{chef_arch}.deb"
directory "/var/cache/chef" do
action :delete
end
remote_file "#{cache_dir}/#{chef_package}" do
- source "https://packages.chef.io/files/stable/chef/#{chef_version}/ubuntu/#{node[:lsb][:release]}/#{chef_package}"
+ source "https://packages.chef.io/files/stable/chef/#{chef_version}/#{chef_platform}/#{os_release}/#{chef_package}"
owner "root"
group "root"
mode "644"
mode "644"
end
-directory "/etc/chef/trusted_certs" do
- owner "root"
- group "root"
- mode "755"
-end
-
-template "/etc/chef/trusted_certs/verisign.pem" do
- source "verisign.pem.erb"
- owner "root"
- group "root"
- mode "644"
-end
-
directory node[:ohai][:plugin_dir] do
owner "root"
group "root"
systemd_service "chef-client" do
description "Chef client"
exec_start "/usr/bin/chef-client"
+ nice 10
end
systemd_timer "chef-client" do
service "chef-client.timer" do
action [:enable, :start]
end
-
-service "chef-client.service" do
- action :disable
- subscribes :stop, "service[chef-client.timer]"
-end
--- /dev/null
+#
+# Cookbook:: chef
+# Recipe:: knife
+#
+# Copyright:: 2021, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+package %w[
+ gcc
+ g++
+ libc6-dev
+ make
+]
+
+chef_gem "knife"
# limitations under the License.
#
+include_recipe "chef::knife"
include_recipe "git"
keys = data_bag_item("chef", "keys")
#
include_recipe "apache"
-include_recipe "munin"
+include_recipe "chef::knife"
# cache_dir = Chef::Config[:file_cache_path]
#
# end
#
# remote_file "#{cache_dir}/#{chef_package}" do
-# source "https://packages.chef.io/files/stable/chef-server/#{chef_version}/ubuntu/16.04/#{chef_package}"
+# source "https://packages.chef.io/files/stable/chef-server/#{chef_version}/ubuntu/20.04/chef-server-core_#{chef_version}-1_amd64.deb"
# owner "root"
# group "root"
# mode 0644
group "root"
mode "755"
end
-
-munin_plugin "chef_status"
ServerAlias chef.osm.org
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/chef.openstreetmap.org-access.log combined
+ CustomLog /var/log/apache2/chef.openstreetmap.org-access.log combined_extended
ErrorLog /var/log/apache2/chef.openstreetmap.org-error.log
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
ServerName chef.openstreetmap.org
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/chef.openstreetmap.org-access.log combined
+ CustomLog /var/log/apache2/chef.openstreetmap.org-access.log combined_extended
ErrorLog /var/log/apache2/chef.openstreetmap.org-error.log
SSLEngine on
umask 0002
unset GIT_DIR
+knife="/opt/chef/embedded/bin/knife"
+
while read oldrev newrev refname
do
if [[ "$refname" = "refs/heads/master" ]]
if [[ $file == roles/*.rb ]]
then
case "$action" in
- A|M) knife role from file "${file}";;
- D) knife role delete -y "${file:t:r}";;
+ A|M) $knife role from file "${file}";;
+ D) $knife role delete -y "${file:t:r}";;
esac
elif [[ $file == data_bags/*/*.json ]]
then
case "$action" in
A|M)
- knife data bag create "${file:h:t}"
- knife data bag from file "${file:h:t}" "${file:t}";;
+ $knife data bag create "${file:h:t}"
+ $knife data bag from file "${file:h:t}" "${file:t}";;
D)
- knife data bag delete -y "${file:h:t}" "${file:t:r}";;
+ $knife data bag delete -y "${file:h:t}" "${file:t:r}";;
esac
elif [[ $file == cookbooks/* ]]
then
if [[ -n "$updated_cookbooks" ]]
then
- knife cookbook upload "${(ou)updated_cookbooks[@]}"
+ $knife cookbook upload "${(ou)updated_cookbooks[@]}"
fi
if [[ -n "$deleted_cookbooks" ]]
then
for cookbook in "${(ou)deleted_cookbooks[@]}"
do
- knife cookbook delete -y "$cookbook"
+ $knife cookbook delete -y "$cookbook"
done
fi
fi
+++ /dev/null
------BEGIN CERTIFICATE-----
-MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkG
-A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
-cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
-MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
-BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
-YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
-BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
-I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
-CSqGSIb3DQEBBQUAA4GBABByUqkFFBkyCEHwxWsKzH4PIRnN5GfcX6kb5sroc50i
-2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWXbj9T/UWZYB2oK0z5XqcJ
-2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/D/xwzoiQ
------END CERTIFICATE-----
# CiviCRM Cookbook
This cookbook installs CiviCRM for Wordpress, and configures it for use with
-join.osmfoundation.org for OSMF memberships.
+supporting.openstreetmap.org (formerly join.osmfoundation.org) for OSMF memberships.
-default[:civicrm][:version] = "5.37.2"
+default[:civicrm][:version] = "5.69.4"
-default[:civicrm][:extensions][:cividiscount][:name] = "org.civicrm.module.cividiscount"
-default[:civicrm][:extensions][:cividiscount][:repository] = "https://github.com/dlobo/org.civicrm.module.cividiscount.git"
-default[:civicrm][:extensions][:cividiscount][:revision] = "3.8.3"
-
-default[:civicrm][:extensions][:osm][:name] = "de.systopia.osm"
-default[:civicrm][:extensions][:osm][:repository] = "https://github.com/systopia/de.systopia.osm.git"
-default[:civicrm][:extensions][:osm][:revision] = "1.3"
+# was used for SotM
+# default[:civicrm][:extensions][:cividiscount][:name] = "org.civicrm.module.cividiscount"
+# default[:civicrm][:extensions][:cividiscount][:repository] = "https://lab.civicrm.org/extensions/cividiscount.git"
+# default[:civicrm][:extensions][:cividiscount][:revision] = "3.8.8"
+# used to email people from civicrm
default[:civicrm][:extensions][:emailapi][:name] = "org.civicoop.emailapi"
default[:civicrm][:extensions][:emailapi][:repository] = "https://lab.civicrm.org/extensions/emailapi.git"
-default[:civicrm][:extensions][:emailapi][:revision] = "2.2"
-
-default[:civicrm][:extensions][:civiruleshttppost][:name] = "org.civicoop.civiruleshttppost"
-default[:civicrm][:extensions][:civiruleshttppost][:repository] = "https://github.com/CiviCooP/org.civicoop.civiruleshttppost.git"
-default[:civicrm][:extensions][:civiruleshttppost][:revision] = "e2c7de5f0fee319b9fca8adb1d1e122202bd2bec"
+default[:civicrm][:extensions][:emailapi][:revision] = "2.12"
-default[:civicrm][:extensions][:civirules][:name] = "org.civicoop.civirules"
-default[:civicrm][:extensions][:civirules][:repository] = "https://lab.civicrm.org/extensions/civirules.git"
-default[:civicrm][:extensions][:civirules][:revision] = "2.23"
-
-default[:civicrm][:extensions][:mailchimp][:name] = "uk.co.vedaconsulting.mailchimp"
-default[:civicrm][:extensions][:mailchimp][:repository] = "https://github.com/veda-consulting/uk.co.vedaconsulting.mailchimp.git"
-default[:civicrm][:extensions][:mailchimp][:revision] = "0065ee6de2c2d653e49d10e9563349e8ffb1f9be"
+# fancy email templates - INSTALL MANUALLY, NOT FROM GIT
+default[:civicrm][:extensions][:mosaico][:name] = "uk.co.vedaconsulting.mosaico"
+default[:civicrm][:extensions][:mosaico][:zip] = "https://download.civicrm.org/extension/uk.co.vedaconsulting.mosaico/3.3.1697392242/uk.co.vedaconsulting.mosaico-3.3.1697392242.zip"
+# validate that osm username exists, simple check
default[:civicrm][:extensions][:username][:name] = "org.openstreetmap.username"
default[:civicrm][:extensions][:username][:repository] = "https://github.com/grischard/org.openstreetmap.username.git"
-default[:civicrm][:extensions][:username][:revision] = "master"
+default[:civicrm][:extensions][:username][:revision] = "9d67583bd3e0342a9770cde48f23586f707012ee"
+# do not send report emails if daily report is empty (mwg)
default[:civicrm][:extensions][:donotsendreportemail][:name] = "org.civicrm.donotsendreportemail"
default[:civicrm][:extensions][:donotsendreportemail][:repository] = "https://github.com/pradpnayak/org.civicrm.donotsendreportemail.git"
-default[:civicrm][:extensions][:donotsendreportemail][:revision] = "3b31c2e0c62183872c7ecd244395fb8dcfbd5dbb"
+default[:civicrm][:extensions][:donotsendreportemail][:revision] = "1.0"
+
+# make civicrm look nicer
+default[:civicrm][:extensions][:theisland][:name] = "theisland"
+default[:civicrm][:extensions][:theisland][:repository] = "https://lab.civicrm.org/extensions/theisland.git"
+default[:civicrm][:extensions][:theisland][:revision] = "2.3.1"
+
+# civiprospect
+default[:civicrm][:extensions][:civiprospect][:name] = "uk.co.compucorp.civicrm.prospect"
+default[:civicrm][:extensions][:civiprospect][:repository] = "https://github.com/compucorp/uk.co.compucorp.civicrm.prospect.git"
+default[:civicrm][:extensions][:civiprospect][:revision] = "3.1.2"
+
+# advanced fundraising reports
+default[:civicrm][:extensions][:advancedfundraisingreports][:name] = "net.ourpowerbase.report.advancedfundraising"
+default[:civicrm][:extensions][:advancedfundraisingreports][:repository] = "https://github.com/jmcclelland/net.ourpowerbase.report.advancedfundraising.git"
+default[:civicrm][:extensions][:advancedfundraisingreports][:revision] = "3d5bd6cab70ba338bc85d42b4853dd4a6f8c9f9b"
+
+# membership churn report
+default[:civicrm][:extensions][:membershipchurn][:name] = "uk.co.vedaconsulting.membershipchurnchart"
+default[:civicrm][:extensions][:membershipchurn][:repository] = "https://github.com/veda-consulting/uk.co.vedaconsulting.membershipchurnchart.git"
+default[:civicrm][:extensions][:membershipchurn][:revision] = "v1.1"
+
+# pivot reports for civiprospect
+default[:civicrm][:extensions][:pivotreport][:name] = "uk.co.compucorp.civicrm.pivotreport"
+default[:civicrm][:extensions][:pivotreport][:repository] = "https://github.com/compucorp/uk.co.compucorp.civicrm.pivotreport.git"
+default[:civicrm][:extensions][:pivotreport][:revision] = "2.0.7"
+
+# extra rules for membership renewal
+default[:civicrm][:extensions][:membershipextra][:name] = "com.skvare.membershipextra"
+default[:civicrm][:extensions][:membershipextra][:repository] = "https://github.com/Skvare/com.skvare.membershipextra.git"
+default[:civicrm][:extensions][:membershipextra][:revision] = "41edc3c04d49987006500b7426b38c12470446b3"
+
+# Verify active contributor status
+default[:civicrm][:extensions][:osmfverifycontributor][:name] = "osmf-verify-contributor"
+default[:civicrm][:extensions][:osmfverifycontributor][:repository] = "https://github.com/openstreetmap/osmf-verify-contributor.git"
+default[:civicrm][:extensions][:osmfverifycontributor][:revision] = "bb0cd61783033fb2e108c30e47224e5a818987f8"
+
+# Pay with Mollie
+default[:civicrm][:extensions][:omnipay][:name] = "nz.co.fuzion.omnipaymultiprocessor"
+default[:civicrm][:extensions][:omnipay][:repository] = "https://github.com/eileenmcnaughton/nz.co.fuzion.omnipaymultiprocessor.git"
+default[:civicrm][:extensions][:omnipay][:revision] = "3.23"
+
+# Pay with Stripe
+default[:civicrm][:extensions][:stripe][:name] = "com.drastikbydesign.stripe"
+default[:civicrm][:extensions][:stripe][:repository] = "https://lab.civicrm.org/extensions/stripe.git"
+default[:civicrm][:extensions][:stripe][:revision] = "6.9.4"
+
+# Stripe requires mjwshared ("payment shared")
+default[:civicrm][:extensions][:mjwshared][:name] = "com.mjwconsult.mjwshared"
+default[:civicrm][:extensions][:mjwshared][:repository] = "https://lab.civicrm.org/extensions/mjwshared.git"
+default[:civicrm][:extensions][:mjwshared][:revision] = "1.2.20"
+
+# Stripe requires sweetalert
+default[:civicrm][:extensions][:sweetalert][:name] = "org.civicrm.sweetalert"
+default[:civicrm][:extensions][:sweetalert][:repository] = "https://lab.civicrm.org/extensions/sweetalert.git"
+default[:civicrm][:extensions][:sweetalert][:revision] = "1.5"
-default[:civicrm][:extensions][:shoreditch][:name] = "org.civicrm.shoreditch"
-default[:civicrm][:extensions][:shoreditch][:repository] = "https://github.com/civicrm/org.civicrm.shoreditch.git"
-default[:civicrm][:extensions][:shoreditch][:revision] = "1.0.0-beta.7"
+# Stripe requires firewall
+default[:civicrm][:extensions][:firewall][:name] = "org.civicrm.firewall"
+default[:civicrm][:extensions][:firewall][:repository] = "https://lab.civicrm.org/extensions/firewall.git"
+default[:civicrm][:extensions][:firewall][:revision] = "1.5.9"
php-xml
php-curl
rsync
- unzip
wkhtmltopdf
php-bcmath
+ php-intl
]
+apache_module "rewrite"
+
cache_dir = Chef::Config[:file_cache_path]
passwords = data_bag_item("civicrm", "passwords")
+wp2fa_encrypt_keys = data_bag_item("civicrm", "wp2fa_encrypt_keys")
database_password = passwords["database"]
-site_key = passwords["key"]
+site_key = passwords["site_key"]
+cred_keys = passwords["cred_keys"]
+sign_keys = passwords["sign_keys"]
mysql_user "civicrm@localhost" do
password database_password
permissions "civicrm@localhost" => :all
end
-wordpress_site "join.osmfoundation.org" do
- aliases "crm.osmfoundation.org"
+wordpress_site "supporting.openstreetmap.org" do
+ aliases %w[
+ crm.osmfoundation.org
+ donate.openstreetmap.org
+ donate.openstreetmap.com
+ donate.openstreetmap.net
+ donate.osm.org
+ join.osmfoundation.org
+ supporting.osmfoundation.org
+ support.osmfoundation.org
+ support.openstreetmap.org
+ supporting.osm.org
+ support.osm.org
+ ]
database_name "civicrm"
database_user "civicrm"
database_password database_password
+ wp2fa_encrypt_key wp2fa_encrypt_keys["key"]
fpm_prometheus_port 11301
end
-wordpress_theme "osmblog-wp-theme" do
- site "join.osmfoundation.org"
- repository "https://github.com/harry-wood/osmblog-wp-theme.git"
+wordpress_plugin "civicrm-wp-piwik" do
+ plugin "wp-piwik"
+ site "supporting.openstreetmap.org"
end
wordpress_plugin "registration-honeypot" do
- site "join.osmfoundation.org"
-end
-
-wordpress_plugin "sitepress-multilingual-cms" do
- site "join.osmfoundation.org"
- repository "https://git.openstreetmap.org/private/sitepress-multilingual-cms.git"
- not_if { ENV["TEST_KITCHEN"] }
+ site "supporting.openstreetmap.org"
end
wordpress_plugin "contact-form-7" do
- site "join.osmfoundation.org"
+ site "supporting.openstreetmap.org"
end
wordpress_plugin "civicrm-admin-utilities" do
- site "join.osmfoundation.org"
+ site "supporting.openstreetmap.org"
+end
+
+wordpress_plugin "host-webfonts-local" do
+ site "supporting.openstreetmap.org"
end
civicrm_version = node[:civicrm][:version]
-civicrm_directory = "/srv/join.osmfoundation.org/wp-content/plugins/civicrm"
+civicrm_directory = "/srv/supporting.openstreetmap.org/wp-content/plugins/civicrm"
directory "/opt/civicrm-#{civicrm_version}" do
owner "wordpress"
backup false
end
-execute "#{cache_dir}/civicrm-#{civicrm_version}-wordpress.zip" do
+archive_file "#{cache_dir}/civicrm-#{civicrm_version}-wordpress.zip" do
action :nothing
- command "unzip -o -qq #{cache_dir}/civicrm-#{civicrm_version}-wordpress.zip"
- cwd "/opt/civicrm-#{civicrm_version}"
- user "wordpress"
+ destination "/opt/civicrm-#{civicrm_version}"
+ overwrite true
+ owner "wordpress"
group "wordpress"
- subscribes :run, "remote_file[#{cache_dir}/civicrm-#{civicrm_version}-wordpress.zip]", :immediately
+ subscribes :extract, "remote_file[#{cache_dir}/civicrm-#{civicrm_version}-wordpress.zip]", :immediately
end
-execute "#{cache_dir}/civicrm-#{civicrm_version}-l10n.tar.gz" do
+archive_file "#{cache_dir}/civicrm-#{civicrm_version}-l10n.tar.gz" do
action :nothing
- command "tar -zxf #{cache_dir}/civicrm-#{civicrm_version}-l10n.tar.gz"
- cwd "/opt/civicrm-#{civicrm_version}/civicrm"
- user "wordpress"
+ destination "/opt/civicrm-#{civicrm_version}/civicrm"
+ overwrite true
+ owner "wordpress"
group "wordpress"
- subscribes :run, "remote_file[#{cache_dir}/civicrm-#{civicrm_version}-l10n.tar.gz]", :immediately
+ subscribes :extract, "remote_file[#{cache_dir}/civicrm-#{civicrm_version}-l10n.tar.gz]", :immediately
end
execute "/opt/civicrm-#{civicrm_version}/civicrm" do
action :nothing
- command "rsync --archive --delete /opt/civicrm-#{civicrm_version}/civicrm/ #{civicrm_directory}"
+ command "rsync --archive --delete --delete-delay --delay-updates /opt/civicrm-#{civicrm_version}/civicrm/ #{civicrm_directory}"
user "wordpress"
group "wordpress"
- subscribes :run, "execute[#{cache_dir}/civicrm-#{civicrm_version}-wordpress.zip]", :immediately
- subscribes :run, "execute[#{cache_dir}/civicrm-#{civicrm_version}-l10n.tar.gz]", :immediately
+ subscribes :run, "archive_file[#{cache_dir}/civicrm-#{civicrm_version}-wordpress.zip]", :immediately
+ subscribes :run, "archive_file[#{cache_dir}/civicrm-#{civicrm_version}-l10n.tar.gz]", :immediately
end
-directory "/srv/join.osmfoundation.org/wp-content/uploads" do
+directory "/srv/supporting.openstreetmap.org/wp-content/uploads" do
owner "www-data"
group "www-data"
mode "755"
end
-extensions_directory = "/srv/join.osmfoundation.org/wp-content/plugins/civicrm-extensions"
+extensions_directory = "/srv/supporting.openstreetmap.org/wp-content/plugins/civicrm-extensions"
directory extensions_directory do
owner "wordpress"
end
node[:civicrm][:extensions].each_value do |details|
- git "#{extensions_directory}/#{details[:name]}" do
- action :sync
- repository details[:repository]
- revision details[:revision]
- user "wordpress"
- group "wordpress"
+ if details[:repository]
+ git "#{extensions_directory}/#{details[:name]}" do
+ action :sync
+ repository details[:repository]
+ revision details[:revision]
+ user "wordpress"
+ group "wordpress"
+ end
+ elsif details[:zip]
+ remote_file "#{cache_dir}/#{details[:name]}.zip" do
+ source details[:zip]
+ owner "root"
+ group "root"
+ mode "644"
+ backup false
+ end
+
+ archive_file "#{cache_dir}/#{details[:name]}.zip" do
+ action :nothing
+ destination "#{extensions_directory}/#{details[:name]}"
+ strip_components 1
+ owner "wordpress"
+ group "wordpress"
+ overwrite true
+ subscribes :extract, "remote_file[#{cache_dir}/#{details[:name]}.zip]", :immediately
+ end
end
end
line.gsub!(/%%dbHost%%/, "localhost")
line.gsub!(/%%dbName%%/, "civicrm")
line.gsub!(/%%crmRoot%%/, "#{civicrm_directory}/civicrm/")
- line.gsub!(/%%templateCompileDir%%/, "/srv/join.osmfoundation.org/wp-content/uploads/civicrm/templates_c/")
- line.gsub!(/%%baseURL%%/, "http://join.osmfoundation.org/")
+ line.gsub!(/%%templateCompileDir%%/, "/srv/supporting.openstreetmap.org/wp-content/uploads/civicrm/templates_c/")
+ line.gsub!(/%%baseURL%%/, "http://supporting.openstreetmap.org/")
line.gsub!(/%%siteKey%%/, site_key)
- line.gsub!(%r{// *define\('CIVICRM_CMSDIR', '/path/to/install/root/'\);}, "define('CIVICRM_CMSDIR', '/srv/join.osmfoundation.org');")
+ line.gsub!(/%%credKeys%%/, cred_keys)
+ line.gsub!(/%%signKeys%%/, sign_keys)
+ line.gsub!(%r{// *define\('CIVICRM_CMSDIR', '/path/to/install/root/'\);}, "define('CIVICRM_CMSDIR', '/srv/supporting.openstreetmap.org');")
line
end
content settings
end
-cron_d "osmf-crm" do
- minute "*/15"
+systemd_service "osmf-crm-jobs" do
+ description "Run CRM jobs"
+ exec_start "/usr/bin/php #{civicrm_directory}/civicrm/bin/cli.php -s supporting.openstreetmap.org -u batch -p \"#{passwords['batch']}\" -e Job -a execute"
user "www-data"
- command "php #{civicrm_directory}/civicrm/bin/cli.php -s join.osmfoundation.org -u batch -p \"#{passwords['batch']}\" -e Job -a execute 2>&1 | egrep -v '^PHP (Deprecated|Warning):'"
- mailto "admins@openstreetmap.org"
+ sandbox :enable_network => true
+ memory_deny_write_execute false
+ restrict_address_families "AF_UNIX"
+ read_write_paths "/srv/supporting.openstreetmap.org/wp-content/uploads/civicrm"
+end
+
+systemd_timer "osmf-crm-jobs" do
+ description "Run CRM jobs"
+ on_boot_sec "15m"
+ on_unit_inactive_sec "15m"
+end
+
+service "osmf-crm-jobs.timer" do
+ action [:enable, :start]
end
template "/etc/cron.daily/osmf-crm-backup" do
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+<% [80, 443].each do |port| -%>
+<VirtualHost *:<%= port %>>
+
+ ServerName join.osmfoundation.org
+ ServerAlias crm.osmfoundation.org
+ ServerAlias supporting.osmfoundation.org
+ ServerAlias support.osmfoundation.org
+ ServerAlias support.openstreetmap.org
+ ServerAlias supporting.osm.org
+ ServerAlias support.osm.org
+
+ ServerAdmin webmaster@openstreetmap.org
+
+ RewriteEngine on
+
+<% if port == 80 -%>
+ RewriteRule ^/\.well-known/acme-challenge/(.*)$ http://acme.openstreetmap.org/.well-known/acme-challenge/$1 [R=permanent,L]
+<% end -%>
+<% if port == 443 -%>
+ SSLEngine on
+ SSLCertificateFile /etc/ssl/certs/join.osmfoundation.org.pem
+ SSLCertificateKeyFile /etc/ssl/private/join.osmfoundation.org.key
+<% end -%>
+
+ RewriteRule ^/(.*)$ https://supporting.openstreetmap.org/$1 [R=307,L]
+
+ CustomLog /var/log/apache2/join.osmfoundation.org-access.log combined_extended
+ ErrorLog /var/log/apache2/join.osmfoundation.org-error.log
+
+</VirtualHost>
+
+<% end -%>
echo 'user=civicrm' >> $T/mysqldump.opts
echo 'password=<%= @passwords["database"] %>' >> $T/mysqldump.opts
mysqldump --defaults-file=$T/mysqldump.opts --opt --skip-lock-tables --no-tablespaces civicrm > $T/osmf-crm-$D/civicrm.sql
-ln -s /srv/join.osmfoundation.org $T/osmf-crm-$D/www
+ln -s /srv/supporting.openstreetmap.org $T/osmf-crm-$D/www
export RSYNC_RSH="ssh -ax"
version "1.0.0"
supports "ubuntu"
+depends "accounts"
# limitations under the License.
#
+include_recipe "accounts"
+
package %w[
clamav-daemon
clamav-freshclam
--- /dev/null
+# Community Cookbook
+
+This installs and configures the community.openstreetmap.org website.
--- /dev/null
+default[:accounts][:users][:community][:status] = :role
-name "forum"
+name "community"
maintainer "OpenStreetMap Administrators"
maintainer_email "admins@openstreetmap.org"
license "Apache-2.0"
-description "Installs and configures a roundup server"
+description "Installs and configures community site"
version "1.0.0"
supports "ubuntu"
depends "accounts"
-depends "apache"
+depends "docker"
+depends "exim"
+depends "geoipupdate"
depends "git"
-depends "mysql"
-depends "php"
+depends "ssl"
--- /dev/null
+#
+# Cookbook:: community
+# Recipe:: default
+#
+# Copyright:: 2021, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "accounts"
+include_recipe "docker"
+include_recipe "git"
+include_recipe "ssl"
+
+passwords = data_bag_item("community", "passwords")
+license_keys = data_bag_item("geoipupdate", "license-keys") unless kitchen?
+
+prometheus_servers = search(:node, "recipes:prometheus\\:\\:server").map do |server|
+ server.ipaddresses(:role => :external)
+end.flatten
+
+# Disable any default installed apache2 service. Web server is embedded within the discourse docker container
+service "apache2" do
+ action [:disable, :stop]
+end
+
+directory "/srv/community.openstreetmap.org" do
+ owner "root"
+ group "root"
+ mode "755"
+end
+
+directory "/srv/community.openstreetmap.org/shared" do
+ owner "community"
+ group "community"
+ mode "755"
+end
+
+directory "/srv/community.openstreetmap.org/files" do
+ owner "community"
+ group "community"
+ mode "755"
+end
+
+template "/srv/community.openstreetmap.org/files/update-feeds.atom" do
+ source "update-feeds.atom.erb"
+ owner "community"
+ group "community"
+ mode "644"
+end
+
+git "/srv/community.openstreetmap.org/docker" do
+ action :sync
+ repository "https://github.com/discourse/discourse_docker.git"
+ # Revision pin not possible as launch wrapper automatically updates git repo.
+ revision "main"
+ depth 1
+ user "root"
+ group "root"
+ notifies :run, "notify_group[discourse_container_new_data]"
+ notifies :run, "notify_group[discourse_container_new_web_only]"
+ notifies :run, "notify_group[discourse_container_new_mail_receiver]"
+end
+
+template "/srv/community.openstreetmap.org/docker/containers/data.yml" do
+ source "data.yml.erb"
+ owner "root"
+ group "root"
+ mode "640"
+ variables :passwords => passwords
+ notifies :run, "notify_group[discourse_container_new_data]"
+end
+
+template "/srv/community.openstreetmap.org/docker/containers/web_only.yml" do
+ source "web_only.yml.erb"
+ owner "root"
+ group "root"
+ mode "640"
+ variables :license_keys => license_keys, :passwords => passwords,
+ :prometheus_servers => prometheus_servers
+ notifies :run, "notify_group[discourse_container_new_web_only]"
+end
+
+template "/srv/community.openstreetmap.org/docker/containers/mail-receiver.yml" do
+ source "mail-receiver.yml.erb"
+ owner "root"
+ group "root"
+ mode "640"
+ variables :passwords => passwords
+ notifies :run, "notify_group[discourse_container_new_mail_receiver]"
+end
+
+ssl_certificate "community.openstreetmap.org" do
+ domains ["community.openstreetmap.org", "community.osm.org", "communities.openstreetmap.org", "communities.osm.org", "c.openstreetmap.org", "c.osm.org", "forum.openstreetmap.org", "forum.osm.org"]
+ notifies :run, "notify_group[discourse_container_new_web_only]"
+ notifies :run, "notify_group[discourse_container_new_mail_receiver]"
+end
+
+notify_group "discourse_container_new_web_only" do
+ notifies :run, "execute[discourse_container_data_start]", :immediately # noop if site up
+ notifies :run, "execute[discourse_container_web_only_bootstrap]", :immediately # site up but runs in parallel. Slow
+ notifies :run, "execute[discourse_container_web_only_destroy]", :immediately # site down
+ notifies :run, "execute[discourse_container_data_rebuild]", :immediately # site down
+ notifies :run, "execute[discourse_container_web_only_start]", :immediately # site restore
+end
+
+notify_group "discourse_container_new_data" do
+ notifies :run, "execute[discourse_container_web_only_destroy]", :immediately # site down
+ notifies :run, "execute[discourse_container_data_rebuild]", :immediately # site down
+ notifies :run, "execute[discourse_container_web_only_start]", :immediately # site restore
+end
+
+notify_group "discourse_container_new_mail_receiver" do
+ notifies :run, "execute[discourse_container_mail_receiver_rebuild]", :immediately
+end
+
+# Attempt at a failsafe to ensure all containers are running
+notify_group "discourse_container_ensure_all_running" do
+ action :run
+ notifies :run, "execute[discourse_container_data_start]", :delayed
+ notifies :run, "execute[discourse_container_web_only_start]", :delayed
+ notifies :run, "execute[discourse_container_mail_receiver_start]", :delayed
+end
+
+execute "discourse_container_data_start" do
+ action :nothing
+ command "./launcher start data"
+ cwd "/srv/community.openstreetmap.org/docker/"
+ user "root"
+ group "root"
+end
+
+execute "discourse_container_data_rebuild" do
+ action :nothing
+ command "./launcher rebuild data"
+ cwd "/srv/community.openstreetmap.org/docker/"
+ user "root"
+ group "root"
+end
+
+execute "discourse_container_web_only_bootstrap" do
+ action :nothing
+ command "./launcher bootstrap web_only"
+ cwd "/srv/community.openstreetmap.org/docker/"
+ user "root"
+ group "root"
+end
+
+execute "discourse_container_web_only_destroy" do
+ action :nothing
+ command "./launcher destroy web_only"
+ cwd "/srv/community.openstreetmap.org/docker/"
+ user "root"
+ group "root"
+end
+
+execute "discourse_container_web_only_start" do
+ action :nothing
+ command "./launcher start web_only"
+ cwd "/srv/community.openstreetmap.org/docker/"
+ user "root"
+ group "root"
+end
+
+# Rebuild: Stop Destroy Bootstap Start
+execute "discourse_container_mail_receiver_rebuild" do
+ action :nothing
+ command "./launcher rebuild mail-receiver"
+ cwd "/srv/community.openstreetmap.org/docker/"
+ user "root"
+ group "root"
+end
+
+execute "discourse_container_mail_receiver_start" do
+ action :nothing
+ command "./launcher start mail-receiver"
+ cwd "/srv/community.openstreetmap.org/docker/"
+ user "root"
+ group "root"
+end
+
+template "/etc/cron.daily/community-backup" do
+ source "backup.cron.erb"
+ owner "root"
+ group "root"
+ mode "750"
+end
+
+node.default[:prometheus][:exporters][443] = {
+ :name => "community",
+ :address => "#{node[:prometheus][:address]}:443",
+ :sni => "community.openstreetmap.org"
+}
--- /dev/null
+#!/bin/sh
+
+# DO NOT EDIT - This file is being maintained by Chef
+
+T=$(mktemp -d -t -p /var/tmp community.XXXXXXXXXX)
+D=$(date +%Y-%m-%d)
+B=community-$D.tar.gz
+
+mkdir $T/community-$D
+ln -s /srv/community.openstreetmap.org/docker/containers $T/community-$D/containers
+ln -s /srv/community.openstreetmap.org/shared/web-only $T/community-$D/shared-web-only
+ln -s /srv/community.openstreetmap.org/shared/data/redis_data $T/community-$D/shared-data-redis_data
+ln -s /srv/community.openstreetmap.org/shared/data/postgres_backup $T/community-$D/shared-data-postgres_backup
+
+export RSYNC_RSH="ssh -ax"
+
+nice tar --create --numeric-owner --dereference --directory=$T --warning=no-file-changed community-$D | nice gzip --rsyncable -9 > $T/$B
+nice rsync --preallocate --fuzzy $T/$B backup::backup
+
+rm -rf $T
--- /dev/null
+# A container for all things Data, be sure to set a secret password for
+# discourse account, SOME_SECRET is just an example
+#
+
+templates:
+ - "templates/postgres.13.template.yml"
+ - "templates/redis.template.yml"
+
+# any extra arguments for Docker?
+# docker_args:
+
+params:
+ db_default_text_search_config: "pg_catalog.english"
+
+ ## Set db_shared_buffers to a max of 25% of the total memory.
+ ## will be set automatically by bootstrap based on detected RAM, or you can override
+ db_shared_buffers: "4096MB"
+
+ ## can improve sorting performance, but adds memory usage per-connection
+ #db_work_mem: "40MB"
+
+env:
+ # ensure locale exists in container, you may need to install it
+ LC_ALL: en_US.UTF-8
+ LANG: en_US.UTF-8
+ LANGUAGE: en_US.UTF-8
+
+volumes:
+ - volume:
+ host: /srv/community.openstreetmap.org/shared/data
+ guest: /shared
+ - volume:
+ host: /srv/community.openstreetmap.org/shared/data/log/var-log
+ guest: /var/log
+
+# TODO: SOME_SECRET to a password for the discourse user
+hooks:
+ after_postgres:
+ - exec:
+ stdin: |
+ alter user discourse with password '<%= @passwords["database"] %>';
+ cmd: su - postgres -c 'psql discourse'
+
+ raise_on_fail: false
+ - file:
+ path: /var/spool/cron/crontabs/postgres
+ contents: |
+ # m h dom mon dow command
+ # MAILTO=?
+ 0 4 * * * /var/lib/postgresql/take-database-backup
--- /dev/null
+## this is the incoming mail receiver container template
+##
+## After making changes to this file, you MUST rebuild
+## /var/discourse/launcher rebuild mail-receiver
+##
+## BE *VERY* CAREFUL WHEN EDITING!
+## YAML FILES ARE SUPER SUPER SENSITIVE TO MISTAKES IN WHITESPACE OR ALIGNMENT!
+## visit http://www.yamllint.com/ to validate this file as needed
+
+base_image: discourse/mail-receiver:release
+update_pups: false
+
+expose:
+ - "2500:25" # SMTP
+
+env:
+ LC_ALL: en_US.UTF-8
+ LANG: en_US.UTF-8
+ LANGUAGE: en_US.UTF-8
+
+ ## Where e-mail to your forum should be sent. In general, it's perfectly fine
+ ## to use the same domain as the forum itself here.
+ MAIL_DOMAIN: community.openstreetmap.org
+ POSTCONF_smtpd_tls_key_file: /shared/ssl/ssl.key
+ POSTCONF_smtpd_tls_cert_file: /shared/ssl/ssl.crt
+ POSTCONF_smtpd_tls_security_level: may
+
+ ## The URL of the mail processing endpoint of your Discourse forum.
+ ## This is simply your forum's base URL, with `/admin/email/handle_mail`
+ ## appended. Be careful if you're running a subfolder setup -- in that case,
+ ## the URL needs to have the subfolder included!
+ DISCOURSE_MAIL_ENDPOINT: 'https://community.openstreetmap.org/admin/email/handle_mail'
+
+ ## The master API key of your Discourse forum. You can get this from
+ ## the "API" tab of your admin panel.
+ DISCOURSE_API_KEY: '<%= @passwords["mail_receiver_api_key"] %>'
+
+ ## The username to use for processing incoming e-mail. Unless you have
+ ## renamed the `system` user, you should leave this as-is.
+ DISCOURSE_API_USERNAME: system
+
+volumes:
+ - volume:
+ host: /srv/community.openstreetmap.org/shared/mail-receiver/postfix-spool
+ guest: /var/spool/postfix
+ - volume:
+ host: /etc/ssl/certs/community.openstreetmap.org.pem
+ guest: /shared/ssl/ssl.crt
+ - volume:
+ host: /etc/ssl/private/community.openstreetmap.org.key
+ guest: /shared/ssl/ssl.key
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<feed xmlns="http://www.w3.org/2005/Atom">
+<title type="text" xml:lang="en">OpenStreetMap Forum Update Feed URL</title>
+<link type="application/atom+xml" href="https://community.openstreetmap.org/update-feeds.atom" rel="self"/>
+<link type="text/html" href="https://community.openstreetmap.org/" rel="alternate"/>
+<updated>2023-03-06T22:00:00Z</updated>
+<id>urn:uuid:1a19dde4-c98d-42ed-8f63-36674f06036a</id>
+<author>
+<name>OpenStreetMap Forum</name>
+</author>
+<rights>Public Domain</rights>
+<entry>
+<title>Update your Forum Feed URLs</title>
+<link href="https://community.openstreetmap.org/"/>
+<updated>2023-03-06T22:00:00Z</updated>
+<id>urn:uuid:1a19dde4-c98d-42ed-8f63-36674f06036f</id>
+<content type="html">forum.openstreetmap.org has been migrated to community.openstreetmap.org. The URLs of the feeds have been updated. Please update your RSS or Atom feed links.</content>
+</entry>
+</feed>
--- /dev/null
+templates:
+ - "templates/web.template.yml"
+ - "templates/web.ipv6.template.yml"
+ - "templates/web.ssl.template.yml"
+
+## which TCP/IP ports should this container expose?
+## If you want Discourse to share a port with another webserver like Apache or nginx,
+## see https://meta.discourse.org/t/17247 for details
+expose:
+ - "80:80" # http
+ - "443:443" # https
+
+# Use 'links' key to link containers together, aka use Docker --link flag.
+links:
+ - link:
+ name: data
+ alias: data
+
+# any extra arguments for Docker?
+# docker_args:
+
+# Latest Version v3.2.1
+params:
+ version: stable
+
+env:
+ LC_ALL: en_US.UTF-8
+ LANG: en_US.UTF-8
+ LANGUAGE: en_US.UTF-8
+ DISCOURSE_FORCE_HTTPS: true
+
+ ## How many concurrent web requests are supported? Depends on memory and CPU cores.
+ ## will be set automatically by bootstrap based on detected CPUs, or you can override
+ UNICORN_WORKERS: <%= node.cpu_cores %>
+
+ ## TODO: The domain name this Discourse instance will respond to
+ DISCOURSE_HOSTNAME: community.openstreetmap.org
+ DISCOURSE_CDN_URL: https://community-cdn.openstreetmap.org
+
+ ## Uncomment if you want the container to be started with the same
+ ## hostname (-h option) as specified above (default "$hostname-$config")
+ #DOCKER_USE_HOSTNAME: true
+
+ ## TODO: List of comma delimited emails that will be made admin and developer
+ ## on initial signup example 'user1@example.com,user2@example.com'
+ DISCOURSE_DEVELOPER_EMAILS: 'operations@openstreetmap.org'
+
+ DISCOURSE_SMTP_ADDRESS: <%= node[:exim][:smarthost_via].split(":", 2)[0] %>
+ DISCOURSE_SMTP_PORT: <%= node[:exim][:smarthost_via].split(":", 2)[1] || "25" %>
+ DISCOURSE_SMTP_OPENSSL_VERIFY_MODE: none
+ DISCOURSE_SMTP_USER_NAME:
+ DISCOURSE_SMTP_PASSWORD:
+ DISCOURSE_SMTP_DOMAIN: community.openstreetmap.org
+ DISCOURSE_SMTP_OPEN_TIMEOUT: 30
+ DISCOURSE_SMTP_READ_TIMEOUT: 30
+ DISCOURSE_NOTIFICATION_EMAIL: community@noreply.openstreetmap.org
+
+ ## TODO: configure connectivity to the databases
+ DISCOURSE_DB_SOCKET: ''
+ #DISCOURSE_DB_USERNAME: discourse
+ DISCOURSE_DB_PASSWORD: '<%= @passwords["database"] %>'
+ DISCOURSE_DB_HOST: data
+ DISCOURSE_REDIS_HOST: data
+
+ ## The maxmind geolocation IP address key for IP address lookup
+ ## see https://meta.discourse.org/t/-/137387/23 for details
+<% if @license_keys -%>
+ DISCOURSE_MAXMIND_LICENSE_KEY: '<%= @license_keys[node[:geoipupdate][:account]] %>'
+<% end -%>
+
+ # Allow list for prometheus metric collection
+ DISCOURSE_PROMETHEUS_TRUSTED_IP_ALLOWLIST_REGEX: '^<%= @prometheus_servers.map { |a| Regexp.escape(a) }.join("|") %>$'
+
+ # Increase base SIDEKIQ memory limit to 1GB
+ UNICORN_SIDEKIQ_MAX_RSS: 1000
+
+volumes:
+ - volume:
+ host: /srv/community.openstreetmap.org/shared/web-only
+ guest: /shared
+ - volume:
+ host: /srv/community.openstreetmap.org/shared/web-only/log/var-log
+ guest: /var/log
+ - volume:
+ host: /etc/ssl/certs/community.openstreetmap.org.pem
+ guest: /shared/ssl/ssl.crt
+ - volume:
+ host: /etc/ssl/private/community.openstreetmap.org.key
+ guest: /shared/ssl/ssl.key
+ - volume:
+ host: /etc/ssl/certs/dhparam.pem
+ guest: /shared/ssl/dhparam.pem
+ - volume:
+ host: /srv/community.openstreetmap.org/files/update-feeds.atom
+ guest: /shared/feeds/update-feeds.atom
+
+## Plugins go here
+## see https://meta.discourse.org/t/19157 for details
+hooks:
+ after_code:
+ - exec:
+ cd: $home/plugins
+ cmd:
+ - sudo -H -E -u discourse git clone --depth 1 --branch main https://github.com/discourse/discourse-oauth2-basic.git
+ - sudo -H -E -u discourse git clone --depth 1 --branch main https://github.com/discourse/discourse-solved.git
+ - sudo -H -E -u discourse git clone --depth 1 --branch main https://github.com/discourse/discourse-reactions.git
+ - sudo -H -E -u discourse git clone --depth 1 --branch main https://github.com/discourse/discourse-prometheus.git
+ - sudo -H -E -u discourse git clone --depth 1 --branch main https://github.com/discourse/discourse-translator.git
+ - sudo -H -E -u discourse git clone --depth 1 --branch main https://github.com/discourse/discourse-saved-searches.git
+ - sudo -H -E -u discourse git clone --depth 1 --branch main https://github.com/discourse/discourse-post-voting.git
+ - exec:
+ # Needs to be copied in else builtin git cleanup fails
+ cd: $home
+ cmd:
+ - sudo -H -E -u discourse cp /shared/feeds/update-feeds.atom public/update-feeds.atom
+ after_ssl:
+ - replace:
+ filename: "/etc/nginx/conf.d/discourse.conf"
+ from: /listen 80;/
+ to: |
+ listen 80;
+ listen [::]:80;
+ rewrite ^/\.well-known/acme-challenge/(.*)$ http://acme.openstreetmap.org/.well-known/acme-challenge/$1 permanent;
+
+ - replace:
+ filename: "/etc/nginx/conf.d/discourse.conf"
+ from: /add_header.+/
+ to: |
+ add_header Strict-Transport-Security 'max-age=63072000' always;
+ ssl_stapling on;
+ resolver <%= node[:networking][:nameservers].join(" ") %>;
+ resolver_timeout 5s;
+ ssl_dhparam /shared/ssl/dhparam.pem;
-default[:db][:cluster] = "9.5/main"
+default[:db][:cluster] = "15/main"
-default[:postgresql][:versions] |= ["9.5"]
+default[:postgresql][:versions] |= ["15"]
+default[:postgresql][:monitor_database] = "openstreetmap"
--- /dev/null
+REINDEX (VERBOSE) TABLE CONCURRENTLY acls;
+REINDEX (VERBOSE) TABLE CONCURRENTLY active_storage_attachments;
+REINDEX (VERBOSE) TABLE CONCURRENTLY active_storage_blobs;
+REINDEX (VERBOSE) TABLE CONCURRENTLY active_storage_variant_records;
+REINDEX (VERBOSE) TABLE CONCURRENTLY ar_internal_metadata;
+REINDEX (VERBOSE) TABLE CONCURRENTLY changeset_comments;
+REINDEX (VERBOSE) TABLE CONCURRENTLY changeset_tags;
+REINDEX (VERBOSE) TABLE CONCURRENTLY changesets;
+REINDEX (VERBOSE) TABLE CONCURRENTLY changesets_subscribers;
+REINDEX (VERBOSE) TABLE CONCURRENTLY client_applications;
+REINDEX (VERBOSE) TABLE CONCURRENTLY current_relation_members;
+REINDEX (VERBOSE) TABLE CONCURRENTLY delayed_jobs;
+REINDEX (VERBOSE) TABLE CONCURRENTLY diary_comments;
+REINDEX (VERBOSE) TABLE CONCURRENTLY diary_entries;
+REINDEX (VERBOSE) TABLE CONCURRENTLY diary_entry_subscriptions;
+REINDEX (VERBOSE) TABLE CONCURRENTLY friends;
+REINDEX (VERBOSE) TABLE CONCURRENTLY gpx_files;
+REINDEX (VERBOSE) TABLE CONCURRENTLY gpx_file_tags;
+REINDEX (VERBOSE) TABLE CONCURRENTLY issue_comments;
+REINDEX (VERBOSE) TABLE CONCURRENTLY issues;
+REINDEX (VERBOSE) TABLE CONCURRENTLY languages;
+REINDEX (VERBOSE) TABLE CONCURRENTLY messages;
+REINDEX (VERBOSE) TABLE CONCURRENTLY note_comments;
+REINDEX (VERBOSE) TABLE CONCURRENTLY notes;
+REINDEX (VERBOSE) TABLE CONCURRENTLY oauth_access_grants;
+REINDEX (VERBOSE) TABLE CONCURRENTLY oauth_access_tokens;
+REINDEX (VERBOSE) TABLE CONCURRENTLY oauth_applications;
+REINDEX (VERBOSE) TABLE CONCURRENTLY oauth_nonces;
+REINDEX (VERBOSE) TABLE CONCURRENTLY oauth_tokens;
+REINDEX (VERBOSE) TABLE CONCURRENTLY redactions;
+REINDEX (VERBOSE) TABLE CONCURRENTLY reports;
+REINDEX (VERBOSE) TABLE CONCURRENTLY schema_migrations;
+REINDEX (VERBOSE) TABLE CONCURRENTLY user_blocks;
+REINDEX (VERBOSE) TABLE CONCURRENTLY user_mutes;
+REINDEX (VERBOSE) TABLE CONCURRENTLY user_preferences;
+REINDEX (VERBOSE) TABLE CONCURRENTLY user_roles;
+REINDEX (VERBOSE) TABLE CONCURRENTLY users;
--- /dev/null
+REINDEX (VERBOSE) TABLE CONCURRENTLY current_node_tags;
+REINDEX (VERBOSE) TABLE CONCURRENTLY current_nodes;
+REINDEX (VERBOSE) TABLE CONCURRENTLY current_relation_tags;
+REINDEX (VERBOSE) TABLE CONCURRENTLY current_relations;
+REINDEX (VERBOSE) TABLE CONCURRENTLY current_way_nodes;
+REINDEX (VERBOSE) TABLE CONCURRENTLY current_way_tags;
+REINDEX (VERBOSE) TABLE CONCURRENTLY current_ways;
+REINDEX (VERBOSE) TABLE CONCURRENTLY gps_points;
+REINDEX (VERBOSE) TABLE CONCURRENTLY node_tags;
+REINDEX (VERBOSE) TABLE CONCURRENTLY nodes;
+REINDEX (VERBOSE) TABLE CONCURRENTLY relation_members;
+REINDEX (VERBOSE) TABLE CONCURRENTLY relation_tags;
+REINDEX (VERBOSE) TABLE CONCURRENTLY relations;
+REINDEX (VERBOSE) TABLE CONCURRENTLY way_nodes;
+REINDEX (VERBOSE) TABLE CONCURRENTLY way_tags;
+REINDEX (VERBOSE) TABLE CONCURRENTLY ways;
depends "git"
depends "postgresql"
depends "python"
+depends "ruby"
+depends "systemd"
depends "web"
mode "755"
end
-cron_d "backup-db" do
- minute "00"
- hour "02"
- weekday "1"
+systemd_service "backup-db" do
+ description "Database backup"
+ exec_start "/usr/local/bin/backup-db"
user "osmbackup"
- command "/usr/local/bin/backup-db"
- mailto "admins@openstreetmap.org"
+ sandbox :enable_network => true
+ restrict_address_families "AF_UNIX"
+ read_write_paths "/store/backup"
+end
+
+systemd_timer "backup-db" do
+ description "Database backup"
+ on_calendar "Mon 02:00 #{node[:timezone]}"
+end
+
+service "backup-db.timer" do
+ action [:enable, :start]
end
include_recipe "git"
include_recipe "postgresql"
include_recipe "python"
+include_recipe "ruby"
passwords = data_bag_item("db", "passwords")
wal_secrets = data_bag_item("db", "wal-secrets")
-ruby_version = node[:passenger][:ruby_version]
-db_version = node[:db][:cluster].split("/").first
-pg_config = "/usr/lib/postgresql/#{db_version}/bin/pg_config"
-function_directory = "/srv/www.openstreetmap.org/rails/db/functions/#{db_version}"
-
-postgresql_munin "openstreetmap" do
- cluster node[:db][:cluster]
- database "openstreetmap"
-end
-
directory "/srv/www.openstreetmap.org" do
group "rails"
mode "2775"
end
rails_port "www.openstreetmap.org" do
- ruby ruby_version
directory "/srv/www.openstreetmap.org/rails"
user "rails"
group "rails"
database_name "openstreetmap"
database_username "openstreetmap"
database_password passwords["openstreetmap"]
- gpx_dir "/store/rails/gpx"
-end
-
-directory function_directory do
- owner "rails"
- group "rails"
- mode "755"
-end
-
-execute function_directory do
- action :nothing
- command "make BUNDLE=bundle#{ruby_version} PG_CONFIG=#{pg_config} DESTDIR=#{function_directory}"
- cwd "/srv/www.openstreetmap.org/rails/db/functions"
- user "rails"
- group "rails"
- subscribes :run, "directory[#{function_directory}]"
- subscribes :run, "git[/srv/www.openstreetmap.org/rails]"
-end
-
-link "/usr/lib/postgresql/#{db_version}/lib/libpgosm.so" do
- to "#{function_directory}/libpgosm.so"
- owner "root"
- group "root"
end
package %w[
git "/opt/osmdbt" do
action :sync
repository "https://github.com/openstreetmap/osmdbt.git"
- revision "v0.2"
+ revision "v0.5"
depth 1
user "root"
group "root"
end
-directory "/opt/osmdbt/build-#{db_version}" do
- owner "root"
- group "root"
- mode "755"
-end
-
-execute "/opt/osmdbt/CMakeLists.txt" do
- action :nothing
- command "cmake -DPG_CONFIG=/usr/lib/postgresql/#{db_version}/bin/pg_config .."
- cwd "/opt/osmdbt/build-#{db_version}"
- user "root"
- group "root"
- subscribes :run, "git[/opt/osmdbt]"
+node[:postgresql][:versions].each do |db_version|
+ directory "/opt/osmdbt/build-#{db_version}" do
+ owner "root"
+ group "root"
+ mode "755"
+ end
+
+ execute "/opt/osmdbt/build-#{db_version}" do
+ action :nothing
+ command "cmake -DPG_CONFIG=/usr/lib/postgresql/#{db_version}/bin/pg_config .."
+ cwd "/opt/osmdbt/build-#{db_version}"
+ user "root"
+ group "root"
+ subscribes :run, "directory[/opt/osmdbt/build-#{db_version}]"
+ subscribes :run, "git[/opt/osmdbt]"
+ end
+
+ execute "/opt/osmdbt/build-#{db_version}/postgresql-plugin/Makefile" do
+ action :nothing
+ command "make"
+ cwd "/opt/osmdbt/build-#{db_version}/postgresql-plugin"
+ user "root"
+ group "root"
+ subscribes :run, "execute[/opt/osmdbt/build-#{db_version}]"
+ end
+
+ link "/usr/lib/postgresql/#{db_version}/lib/osm-logical.so" do
+ to "/opt/osmdbt/build-#{db_version}/postgresql-plugin/osm-logical.so"
+ owner "root"
+ group "root"
+ end
end
-execute "/opt/osmdbt/build-#{db_version}/postgresql-plugin/Makefile" do
- action :nothing
- command "make"
- cwd "/opt/osmdbt/build-#{db_version}/postgresql-plugin"
- user "root"
- group "root"
- subscribes :run, "execute[/opt/osmdbt/CMakeLists.txt]"
-end
+package "lzop"
-link "/usr/lib/postgresql/#{db_version}/lib/osm-logical.so" do
- to "/opt/osmdbt/build-#{db_version}/postgresql-plugin/osm-logical.so"
+remote_file "/usr/local/bin/wal-g" do
+ action :create
+ source "https://github.com/wal-g/wal-g/releases/download/v2.0.1/wal-g-pg-ubuntu-20.04-amd64"
owner "root"
group "root"
+ mode "755"
end
-package "lzop"
-
-python_package "wal-e" do
- python_version "3"
-end
-
-python_package "boto" do
- python_version "3"
-end
-
-template "/usr/local/bin/openstreetmap-wal-e" do
- source "wal-e.erb"
+template "/usr/local/bin/openstreetmap-wal-g" do
+ source "wal-g.erb"
owner "root"
group "postgres"
mode "750"
password passwords["rails"]
end
+postgresql_user "cgimap" do
+ cluster node[:db][:cluster]
+ password passwords["cgimap"]
+end
+
postgresql_user "planetdump" do
cluster node[:db][:cluster]
password passwords["planetdump"]
password passwords["backup"]
end
-postgresql_user "gpximport" do
- cluster node[:db][:cluster]
- password passwords["gpximport"]
-end
-
-postgresql_user "munin" do
- cluster node[:db][:cluster]
- password passwords["munin"]
-end
-
postgresql_user "replication" do
cluster node[:db][:cluster]
password passwords["replication"]
only_if { node[:postgresql][:clusters][node[:db][:cluster]] && node[:postgresql][:clusters][node[:db][:cluster]][:version] >= 9.0 }
end
-file "/etc/cron.daily/rails-db" do
- action :delete
+CGIMAP_PERMISSIONS = {
+ "changeset_comments" => [:select],
+ "changeset_tags" => [:select],
+ "changesets" => [:select, :update],
+ "client_applications" => [:select],
+ "current_node_tags" => [:select, :insert, :delete],
+ "current_nodes" => [:select, :insert, :update],
+ "current_nodes_id_seq" => [:update],
+ "current_relation_members" => [:select, :insert, :delete],
+ "current_relation_tags" => [:select, :insert, :delete],
+ "current_relations" => [:select, :insert, :update],
+ "current_relations_id_seq" => [:update],
+ "current_way_nodes" => [:select, :insert, :delete],
+ "current_way_tags" => [:select, :insert, :delete],
+ "current_ways" => [:select, :insert, :update],
+ "current_ways_id_seq" => [:update],
+ "issues" => [:select],
+ "node_tags" => [:select, :insert],
+ "nodes" => [:select, :insert],
+ "oauth_access_grants" => [:select],
+ "oauth_access_tokens" => [:select],
+ "oauth_applications" => [:select],
+ "oauth_nonces" => [:select, :insert],
+ "oauth_nonces_id_seq" => [:update],
+ "oauth_tokens" => [:select],
+ "relation_members" => [:select, :insert],
+ "relation_tags" => [:select, :insert],
+ "relations" => [:select, :insert],
+ "reports" => [:select],
+ "user_blocks" => [:select],
+ "user_roles" => [:select],
+ "users" => [:select],
+ "way_nodes" => [:select, :insert],
+ "way_tags" => [:select, :insert],
+ "ways" => [:select, :insert]
+}.freeze
+
+PLANETDUMP_PERMISSIONS = {
+ "note_comments" => :select,
+ "notes" => :select,
+ "users" => :select
+}.freeze
+
+PLANETDIFF_PERMISSIONS = {
+ "changeset_comments" => :select,
+ "changeset_tags" => :select,
+ "changesets" => :select,
+ "node_tags" => :select,
+ "nodes" => :select,
+ "relation_members" => :select,
+ "relation_tags" => :select,
+ "relations" => :select,
+ "users" => :select,
+ "way_nodes" => :select,
+ "way_tags" => :select,
+ "ways" => :select
+}.freeze
+
+PROMETHEUS_PERMISSIONS = {
+ "delayed_jobs" => :select
+}.freeze
+
+%w[
+ acls
+ active_storage_attachments
+ active_storage_blobs
+ active_storage_variant_records
+ ar_internal_metadata
+ changeset_comments
+ changeset_tags
+ changesets
+ changesets_subscribers
+ client_applications
+ current_node_tags
+ current_nodes
+ current_relation_members
+ current_relation_tags
+ current_relations
+ current_way_nodes
+ current_way_tags
+ current_ways
+ delayed_jobs
+ diary_comments
+ diary_entries
+ diary_entry_subscriptions
+ friends
+ gps_points
+ gpx_file_tags
+ gpx_files
+ issue_comments
+ issues
+ languages
+ messages
+ node_tags
+ nodes
+ note_comments
+ notes
+ oauth_access_grants
+ oauth_access_tokens
+ oauth_applications
+ oauth_nonces
+ oauth_openid_requests
+ oauth_tokens
+ redactions
+ relation_members
+ relation_tags
+ relations
+ reports
+ schema_migrations
+ user_blocks
+ user_mutes
+ user_preferences
+ user_roles
+ users
+ way_nodes
+ way_tags
+ ways
+].each do |table|
+ postgresql_table table do
+ cluster node[:db][:cluster]
+ database "openstreetmap"
+ owner "openstreetmap"
+ permissions "openstreetmap" => [:all],
+ "rails" => [:select, :insert, :update, :delete],
+ "cgimap" => CGIMAP_PERMISSIONS[table],
+ "planetdump" => PLANETDUMP_PERMISSIONS[table],
+ "planetdiff" => PLANETDIFF_PERMISSIONS[table],
+ "prometheus" => PROMETHEUS_PERMISSIONS[table],
+ "backup" => [:select]
+ end
+end
+
+%w[
+ acls_id_seq
+ active_storage_attachments_id_seq
+ active_storage_blobs_id_seq
+ active_storage_variant_records_id_seq
+ changeset_comments_id_seq
+ changesets_id_seq
+ client_applications_id_seq
+ current_nodes_id_seq
+ current_relations_id_seq
+ current_ways_id_seq
+ delayed_jobs_id_seq
+ diary_comments_id_seq
+ diary_entries_id_seq
+ friends_id_seq
+ gpx_file_tags_id_seq
+ gpx_files_id_seq
+ issue_comments_id_seq
+ issues_id_seq
+ messages_id_seq
+ note_comments_id_seq
+ notes_id_seq
+ oauth_access_grants_id_seq
+ oauth_access_tokens_id_seq
+ oauth_applications_id_seq
+ oauth_nonces_id_seq
+ oauth_openid_requests_id_seq
+ oauth_tokens_id_seq
+ redactions_id_seq
+ reports_id_seq
+ user_blocks_id_seq
+ user_mutes_id_seq
+ user_roles_id_seq
+ users_id_seq
+].each do |sequence|
+ postgresql_sequence sequence do
+ cluster node[:db][:cluster]
+ database "openstreetmap"
+ owner "openstreetmap"
+ permissions "openstreetmap" => [:all],
+ "rails" => [:usage],
+ "cgimap" => CGIMAP_PERMISSIONS[sequence],
+ "backup" => [:select]
+ end
+end
+
+cookbook_file "/usr/local/share/monthly-reindex.sql" do
+ owner "root"
+ group "root"
+ mode "644"
+end
+
+systemd_service "monthly-reindex" do
+ description "Monthly database reindex"
+ exec_start "/usr/bin/psql -f /usr/local/share/monthly-reindex.sql openstreetmap"
+ user "postgres"
+ sandbox true
+ restrict_address_families "AF_UNIX"
+ remove_ipc false
+end
+
+systemd_timer "monthly-reindex" do
+ description "Monthly database reindex"
+ on_calendar "Sun *-*-1..7 02:00"
+end
+
+service "monthly-reindex.timer" do
+ action [:enable, :start]
+end
+
+cookbook_file "/usr/local/share/yearly-reindex.sql" do
+ owner "root"
+ group "root"
+ mode "644"
+end
+
+systemd_service "yearly-reindex" do
+ description "Yearly database reindex"
+ exec_start "/usr/bin/psql -f /usr/local/share/yearly-reindex.sql openstreetmap"
+ user "postgres"
+ sandbox true
+ restrict_address_families "AF_UNIX"
+ remove_ipc false
+end
+
+systemd_timer "yearly-reindex" do
+ description "Yearly database reindex"
+ on_calendar "Thu *-1-8..14 02:00"
+end
+
+service "yearly-reindex.timer" do
+ action [:enable, :start]
+end
+
+template "/etc/prometheus/exporters/sql_rails.collector.yml" do
+ source "sql_rails.yml.erb"
+ owner "root"
+ group "root"
+ mode "0644"
end
#
include_recipe "db::base"
+
+service "monthly-reindex.timer" do
+ action [:disable, :stop]
+end
-#!/bin/sh
+#!/bin/sh -e
# DO NOT EDIT - This file is being maintained by Chef
--- /dev/null
+collector_name: sql_rails
+
+metrics:
+ - metric_name: rails_queue_length
+ type: gauge
+ help: Rails job queue length
+ key_labels:
+ - queue
+ - status
+ values: [length]
+ query: |
+ SELECT
+ queue,
+ CASE
+ WHEN failed_at IS NOT NULL THEN 'failed'
+ WHEN locked_at IS NOT NULL THEN 'running'
+ WHEN attempts > 0 THEN 'retry'
+ ELSE 'pending'
+ END AS status,
+ COUNT(*) AS length
+ FROM
+ delayed_jobs
+ GROUP BY
+ queue,
+ status
--- /dev/null
+#!/bin/sh
+
+# DO NOT EDIT - This file is being maintained by Chef
+
+export WALG_S3_PREFIX="s3://openstreetmap-wal/"
+export WALG_COMPRESSION_METHOD="lz4"
+export AWS_ACCESS_KEY_ID="AKIAIQX2LTDOBIW4CZUQ"
+export AWS_SECRET_ACCESS_KEY="<%= @s3_key %>"
+export AWS_REGION="eu-west-2"
+
+exec /usr/local/bin/wal-g "$@" < /dev/null
depends "geoipupdate"
depends "git"
depends "memcached"
-depends "munin"
depends "mysql"
depends "nodejs"
depends "php"
depends "postgresql"
depends "python"
+depends "ruby"
depends "tools"
depends "web"
include_recipe "geoipupdate"
include_recipe "git"
include_recipe "memcached"
-include_recipe "munin"
include_recipe "mysql"
include_recipe "nodejs"
include_recipe "php::fpm"
include_recipe "postgresql"
include_recipe "python"
+include_recipe "ruby"
package %w[
+ ant
+ apache2-dev
+ aria2
+ at
+ autoconf
+ automake
+ awscli
+ cmake
+ composer
+ default-jdk-headless
+ default-jre-headless
+ fonts-dejavu
+ fonts-dejavu-core
+ fonts-dejavu-extra
+ fonts-droid-fallback
+ fonts-liberation
+ fonts-noto-mono
+ g++
+ gcc
+ gdal-bin
+ gnuplot-nox
+ golang
+ graphviz
+ irssi
+ jq
+ libargon2-dev
+ libboost-date-time-dev
+ libboost-dev
+ libboost-filesystem-dev
+ libboost-locale-dev
+ libboost-program-options-dev
+ libboost-regex-dev
+ libboost-system-dev
+ libbrotli-dev
+ libbytes-random-secure-perl
+ libcairo2-dev
+ libcrypto++-dev
+ libcurl4-openssl-dev
+ libfcgi-dev
+ libfmt-dev
+ libglib2.0-dev
+ libiniparser-dev
+ libjson-xs-perl
+ libmapnik-dev
+ libmemcached-dev
+ libpqxx-dev
+ libtool
+ libxml-twig-perl
+ libxml2-dev
+ libyajl-dev
+ lua-any
+ luajit
+ lz4
+ lzip
+ lzop
+ mailutils
+ make
+ nano
+ netcat
+ osm2pgsql
+ osmosis
+ pandoc
+ pandoc
+ pbzip2
+ php-apcu
php-cgi
php-cli
php-curl
php-db
+ php-gd
+ php-igbinary
php-imagick
+ php-intl
+ php-mbstring
+ php-memcache
php-mysql
php-pear
php-pgsql
php-sqlite3
+ php-xml
+ pigz
pngcrush
pngquant
+ proj-bin
+ python-is-python3
python3
+ python3-brotli
python3-bs4
python3-cheetah
python3-dateutil
+ python3-dev
+ python3-dotenv
+ python3-gdal
+ python3-lxml
+ python3-lz4
python3-magic
+ python3-pil
python3-psycopg2
- python3-gdal
- g++
- gcc
- make
- autoconf
- automake
- libtool
- libfcgi-dev
- libxml2-dev
- libmemcached-dev
- libboost-regex-dev
- libboost-system-dev
- libboost-program-options-dev
- libboost-date-time-dev
- libboost-filesystem-dev
- libboost-locale-dev
- libpqxx-dev
- libcrypto++-dev
- libyajl-dev
+ python3-pyproj
+ python3-venv
+ r-base
+ redis
+ tmux
+ unrar
+ unzip
+ whois
+ zip
zlib1g-dev
]
+# Add uk_os_OSTN15_NTv2_OSGBtoETRS.tif used for reprojecting OS data
+execute "uk_os_OSTN15_NTv2_OSGBtoETRS.tif" do
+ command "projsync --file uk_os_OSTN15_NTv2_OSGBtoETRS.tif --system-directory"
+ not_if { ::File.exist?("/usr/share/proj/uk_os_OSTN15_NTv2_OSGBtoETRS.tif") }
+end
+
nodejs_package "svgo"
python_package "geojson" do
"memory_limit" => "128M",
"post_max_size" => "32M",
"upload_max_filesize" => "32M"
- php_admin_values "sendmail_path" => "/usr/sbin/sendmail -t -i -f #{name}@errol.openstreetmap.org",
+ php_admin_values "sendmail_path" => "/usr/sbin/sendmail -t -i -f #{name}@dev.openstreetmap.org",
"open_basedir" => "/home/#{name}/:/tmp/:/usr/share/php/"
php_flags "display_errors" => "on"
end
end
end
-if node[:postgresql][:clusters][:"13/main"]
+node[:postgresql][:versions].each do |version|
+ package "postgresql-#{version}-postgis-3"
+end
+
+if node[:postgresql][:clusters][:"15/main"]
postgresql_user "apis" do
- cluster "13/main"
+ cluster "15/main"
end
template "/usr/local/bin/cleanup-rails-assets" do
mode "755"
end
- ruby_version = node[:passenger][:ruby_version]
-
systemd_service "rails-jobs@" do
description "Rails job queue runner"
type "simple"
+ environment_file "/etc/default/rails-%i"
user "apis"
working_directory "/srv/%i.apis.dev.openstreetmap.org/rails"
- exec_start "/usr/local/bin/bundle#{ruby_version} exec rake jobs:work"
+ exec_start "#{node[:ruby][:bundle]} exec rails jobs:work"
restart "on-failure"
- private_tmp true
- private_devices true
- protect_system "full"
- protect_home true
- no_new_privileges true
+ nice 10
+ sandbox :enable_network => true
+ restrict_address_families "AF_UNIX"
+ memory_deny_write_execute false
+ read_write_paths [
+ "/srv/%i.apis.dev.openstreetmap.org/logs",
+ "/srv/%i.apis.dev.openstreetmap.org/rails/storage"
+ ]
end
systemd_service "cgimap@" do
type "forking"
environment_file "/etc/default/cgimap-%i"
user "apis"
- exec_start "/srv/%i.apis.dev.openstreetmap.org/cgimap/openstreetmap-cgimap --daemon --port $CGIMAP_PORT --instances 5"
+ group "www-data"
+ umask "0002"
+ exec_start "/srv/%i.apis.dev.openstreetmap.org/cgimap/build/openstreetmap-cgimap --daemon --instances 5"
exec_reload "/bin/kill -HUP $MAINPID"
- private_tmp true
- private_devices true
- protect_system "full"
- protect_home true
- no_new_privileges true
+ runtime_directory "cgimap-%i"
+ sandbox :enable_network => true
+ restrict_address_families "AF_UNIX"
+ read_write_paths ["/srv/%i.apis.dev.openstreetmap.org/logs", "/srv/%i.apis.dev.openstreetmap.org/rails/tmp"]
restart "on-failure"
end
- cgimap_port = 9000
+ Dir.glob("/srv/*.apis.dev.openstreetmap.org").each do |dir|
+ node.default_unless[:dev][:rails][File.basename(dir).split(".").first] = {}
+ end
node[:dev][:rails].each do |name, details|
database_name = details[:database] || "apis_#{name}"
secret_key_base = persistent_token("dev", "rails", name, "secret_key_base")
postgresql_database database_name do
- cluster "13/main"
+ cluster "15/main"
owner "apis"
end
postgresql_extension "#{database_name}_btree_gist" do
- cluster "13/main"
+ cluster "15/main"
database database_name
extension "btree_gist"
end
mode "755"
end
+ openssl_rsa_private_key "#{site_directory}/doorkeeper.key" do
+ owner "root"
+ group "root"
+ mode "0400"
+ end
+
rails_port site_name do
- ruby ruby_version
directory rails_directory
user "apis"
group "apis"
repository details[:repository]
revision details[:revision]
- database_port node[:postgresql][:clusters][:"13/main"][:port]
+ database_port node[:postgresql][:clusters][:"15/main"][:port]
database_name database_name
database_username "apis"
email_from "OpenStreetMap <web@noreply.openstreetmap.org>"
csp_enforce true
run_migrations true
trace_use_job_queue true
+ doorkeeper_signing_key lazy { File.read("#{site_directory}/doorkeeper.key") }
end
template "#{rails_directory}/config/initializers/setup.rb" do
notifies :restart, "rails_port[#{site_name}]"
end
+ template "/etc/default/rails-#{name}" do
+ source "rails.environment.erb"
+ owner "root"
+ group "root"
+ mode "0600"
+ variables :secret_key_base => secret_key_base
+ end
+
service "rails-jobs@#{name}" do
action [:enable, :start]
supports :restart => true
subscribes :restart, "rails_port[#{site_name}]"
- subscribes :restart, "systemd_service[#{name}]"
+ subscribes :restart, "systemd_service[rails-jobs@]"
only_if "fgrep -q delayed_job #{rails_directory}/Gemfile.lock"
end
group "apis"
end
- execute "#{cgimap_directory}/autogen.sh" do
- action :nothing
- command "./autogen.sh"
- cwd cgimap_directory
+ directory "#{cgimap_directory}/build" do
user "apis"
group "apis"
- subscribes :run, "git[#{cgimap_directory}]", :immediate
+ mode "0755"
end
- execute "#{cgimap_directory}/configure" do
+ execute "#{cgimap_directory}/CMakeLists.txt" do
action :nothing
- command "./configure --with-fcgi=/usr --with-boost-libdir=/usr/lib/x86_64-linux-gnu --enable-yajl"
- cwd cgimap_directory
+ command "cmake .."
+ cwd "#{cgimap_directory}/build"
user "apis"
group "apis"
- subscribes :run, "execute[#{cgimap_directory}/autogen.sh]", :immediate
+ subscribes :run, "git[#{cgimap_directory}]", :immediately
end
- execute "#{cgimap_directory}/Makefile" do
+ execute "#{cgimap_directory}/build/Makefile" do
action :nothing
command "make -j"
- cwd cgimap_directory
+ cwd "#{cgimap_directory}/build"
user "apis"
group "apis"
- subscribes :run, "execute[#{cgimap_directory}/configure]", :immediate
- notifies :restart, "service[cgimap@#{name}]"
+ subscribes :run, "execute[#{cgimap_directory}/CMakeLists.txt]", :immediately
end
template "/etc/default/cgimap-#{name}" do
owner "root"
group "root"
mode "640"
- variables :cgimap_port => cgimap_port,
- :database_port => node[:postgresql][:clusters][:"13/main"][:port],
+ variables :cgimap_socket => "/run/cgimap-#{name}/socket",
+ :database_port => node[:postgresql][:clusters][:"15/main"][:port],
:database_name => database_name,
- :log_directory => log_directory
- notifies :restart, "service[cgimap@#{name}]"
+ :log_directory => log_directory,
+ :options => details[:cgimap_options]
end
service "cgimap@#{name}" do
action [:start, :enable]
+ subscribes :restart, "execute[#{cgimap_directory}/build/Makefile]"
+ subscribes :restart, "template[/etc/default/cgimap-#{name}]"
+ subscribes :restart, "systemd_service[cgimap@]"
end
end
:aliases => site_aliases,
:secret_key_base => secret_key_base,
:cgimap_enabled => details.key?(:cgimap_repository),
- :cgimap_port => cgimap_port
+ :cgimap_socket => "/run/cgimap-#{name}/socket"
end
template "/etc/logrotate.d/apis-#{name}" do
:log_directory => log_directory,
:rails_directory => rails_directory
end
-
- cgimap_port += 1
else
file "/etc/logrotate.d/apis-#{name}" do
action :delete
action :delete
end
+ service "rails-jobs@#{name}" do
+ action [:stop, :disable]
+ end
+
directory site_directory do
action :delete
recursive true
postgresql_database database_name do
action :drop
- cluster "13/main"
+ cluster "15/main"
end
end
end
apache_site "apis.dev.openstreetmap.org" do
template "apache.apis.erb"
end
-
- node[:postgresql][:clusters].each_key do |name|
- postgresql_munin name do
- cluster name
- database "ALL"
- end
- end
end
directory "/srv/ooc.openstreetmap.org" do
apache_site "ooc.openstreetmap.org" do
template "apache.ooc.erb"
end
+
+directory "/etc/systemd/system/user-.slice.d" do
+ owner "root"
+ group "root"
+ mode "0755"
+end
+
+template "/etc/systemd/system/user-.slice.d/99-chef.conf" do
+ source "user-slice.conf.erb"
+ owner "root"
+ group "root"
+ mode "0644"
+end
SSLCertificateFile /etc/ssl/certs/apis.dev.openstreetmap.org.pem
SSLCertificateKeyFile /etc/ssl/private/apis.dev.openstreetmap.org.key
- CustomLog /var/log/apache2/apis.dev.openstreetmap.org-access.log combined
+ CustomLog /var/log/apache2/apis.dev.openstreetmap.org-access.log combined_extended
ErrorLog /var/log/apache2/apis.dev.openstreetmap.org-error.log
DocumentRoot /srv/apis.dev.openstreetmap.org
ServerName apis.dev.openstreetmap.org
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/apis.dev.openstreetmap.org-access.log combined
+ CustomLog /var/log/apache2/apis.dev.openstreetmap.org-access.log combined_extended
ErrorLog /var/log/apache2/apis.dev.openstreetmap.org-error.log
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
SSLCertificateFile /etc/ssl/certs/dev.openstreetmap.org.pem
SSLCertificateKeyFile /etc/ssl/private/dev.openstreetmap.org.key
- CustomLog /var/log/apache2/dev.openstreetmap.org-access.log combined
+ CustomLog /var/log/apache2/dev.openstreetmap.org-access.log combined_extended
ErrorLog /var/log/apache2/dev.openstreetmap.org-error.log
DocumentRoot /srv/dev.openstreetmap.org
ServerName dev.openstreetmap.org
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/dev.openstreetmap.org-access.log combined
+ CustomLog /var/log/apache2/dev.openstreetmap.org-access.log combined_extended
ErrorLog /var/log/apache2/dev.openstreetmap.org-error.log
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
SSLCertificateFile /etc/ssl/certs/ooc.openstreetmap.org.pem
SSLCertificateKeyFile /etc/ssl/private/ooc.openstreetmap.org.key
- CustomLog /var/log/apache2/ooc.openstreetmap.org-access.log combined
+ CustomLog /var/log/apache2/ooc.openstreetmap.org-access.log combined_extended
ErrorLog /var/log/apache2/ooc.openstreetmap.org-error.log
DocumentRoot /srv/ooc.openstreetmap.org/html
ServerAlias c.ooc.openstreetmap.org
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/ooc.openstreetmap.org-access.log combined
+ CustomLog /var/log/apache2/ooc.openstreetmap.org-access.log combined_extended
ErrorLog /var/log/apache2/ooc.openstreetmap.org-error.log
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
ServerName npe.openstreetmap.org
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/npe.openstreetmap.org-access.log combined
+ CustomLog /var/log/apache2/npe.openstreetmap.org-access.log combined_extended
ErrorLog /var/log/apache2/npe.openstreetmap.org-error.log
RewriteEngine on
SSLCertificateFile /etc/ssl/certs/phppgadmin.dev.openstreetmap.org.pem
SSLCertificateKeyFile /etc/ssl/private/phppgadmin.dev.openstreetmap.org.key
- CustomLog /var/log/apache2/phppgadmin.dev.openstreetmap.org-access.log combined
+ CustomLog /var/log/apache2/phppgadmin.dev.openstreetmap.org-access.log combined_extended
ErrorLog /var/log/apache2/phppgadmin.dev.openstreetmap.org-error.log
DocumentRoot /usr/share/phppgadmin
# Remove Proxy request header to mitigate https://httpoxy.org/
RequestHeader unset Proxy early
- ProxyPassMatch ^/(.*\.php(/.*)?)$ unix:/run/php/default.sock|fcgi://127.0.0.1
- ProxyPassMatch ^/(.*\.phpx(/.*)?)$ unix:/run/php/default.sock|fcgi://127.0.0.1
- ProxyPassMatch ^/(.*\.phpj(/.*)?)$ unix:/run/php/default.sock|fcgi://127.0.0.1
+ ProxyPassMatch ^/(.*\.php(/.*)?)$ unix:/run/php/php-default-fpm.sock|fcgi://127.0.0.1
+ ProxyPassMatch ^/(.*\.phpx(/.*)?)$ unix:/run/php/php-default-fpm.sock|fcgi://127.0.0.1
+ ProxyPassMatch ^/(.*\.phpj(/.*)?)$ unix:/run/php/php-default-fpm.sock|fcgi://127.0.0.1
</VirtualHost>
<VirtualHost *:80>
ServerName phppgadmin.dev.openstreetmap.org
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/phppgadmin.dev.openstreetmap.org-access.log combined
+ CustomLog /var/log/apache2/phppgadmin.dev.openstreetmap.org-access.log combined_extended
ErrorLog /var/log/apache2/phppgadmin.dev.openstreetmap.org-error.log
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
DocumentRoot /srv/<%= @name %>/rails/public
# Pass supported calls to cgimap
RewriteEngine on
- RewriteRule ^/api/0\.6/map(\.json|\.xml)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
+ RewriteRule ^/api/0\.6/map(\.json|\.xml)?$ unix:<%= @cgimap_socket %>|fcgi://127.0.0.1$0 [P]
RewriteCond %{REQUEST_METHOD} ^(HEAD|GET)$
- RewriteRule ^/api/0\.6/(node|way|relation|changeset)/[0-9]+(\.json|\.xml)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
- RewriteRule ^/api/0\.6/(node|way|relation)/[0-9]+/history(\.json|\.xml)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
- RewriteRule ^/api/0\.6/(node|way|relation)/[0-9]+/relations(\.json|\.xml)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
- RewriteRule ^/api/0\.6/node/[0-9]+/ways(\.json|\.xml)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
- RewriteRule ^/api/0\.6/(way|relation)/[0-9]+/full(\.json|\.xml)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
- RewriteRule ^/api/0\.6/(nodes|ways|relations)(\.json|\.xml)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
- RewriteRule ^/api/0\.6/changeset/[0-9]+/(upload|download)(\.json|\.xml)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
+ RewriteRule ^/api/0\.6/(node|way|relation|changeset)/[0-9]+(\.json|\.xml)?$ unix:<%= @cgimap_socket %>|fcgi://127.0.0.1$0 [P]
+ RewriteRule ^/api/0\.6/(node|way|relation)/[0-9]+/history(\.json|\.xml)?$ unix:<%= @cgimap_socket %>|fcgi://127.0.0.1$0 [P]
+ RewriteRule ^/api/0\.6/(node|way|relation)/[0-9]+/relations(\.json|\.xml)?$ unix:<%= @cgimap_socket %>|fcgi://127.0.0.1$0 [P]
+ RewriteRule ^/api/0\.6/node/[0-9]+/ways(\.json|\.xml)?$ unix:<%= @cgimap_socket %>|fcgi://127.0.0.1$0 [P]
+ RewriteRule ^/api/0\.6/(way|relation)/[0-9]+/full(\.json|\.xml)?$ unix:<%= @cgimap_socket %>|fcgi://127.0.0.1$0 [P]
+ RewriteRule ^/api/0\.6/(nodes|ways|relations)(\.json|\.xml)?$ unix:<%= @cgimap_socket %>|fcgi://127.0.0.1$0 [P]
+ RewriteRule ^/api/0\.6/changeset/[0-9]+/(upload|download)(\.json|\.xml)?$ unix:<%= @cgimap_socket %>|fcgi://127.0.0.1$0 [P]
<% end -%>
</VirtualHost>
<% end -%>
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
RewriteEngine on
#LogLevel rewrite:trace2
- CustomLog /var/log/apache2/<%= @user %>.dev.openstreetmap.org-access.log combined
+ CustomLog /var/log/apache2/<%= @user %>.dev.openstreetmap.org-access.log combined_extended
ErrorLog /var/log/apache2/<%= @user %>.dev.openstreetmap.org-error.log
RewriteCond <%= @directory %>%{REQUEST_FILENAME} -f
RewriteRule ^/cgi-bin/(.*)$ /~<%= @user %>/cgi-bin/$1 [PT,L]
<FilesMatch ".+\.ph(p|ps|p3|tml)$">
- SetHandler "proxy:unix:/run/php/<%= @user %>.sock|fcgi://127.0.0.1"
+ SetHandler "proxy:unix:/run/php/php-<%= @user %>-fpm.sock|fcgi://127.0.0.1"
</FilesMatch>
</VirtualHost>
ServerAdmin webmaster@openstreetmap.org
ServerAlias <%= @user %>.dev.osm.org
- CustomLog /var/log/apache2/<%= @user %>.dev.openstreetmap.org-access.log combined
+ CustomLog /var/log/apache2/<%= @user %>.dev.openstreetmap.org-access.log combined_extended
ErrorLog /var/log/apache2/<%= @user %>.dev.openstreetmap.org-error.log
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
# DO NOT EDIT - This file is being maintained by Chef
-CGIMAP_PORT="<%= @cgimap_port %>"
+CGIMAP_SOCKET="<%= @cgimap_socket %>"
CGIMAP_DBPORT="<%= @database_port %>"
CGIMAP_DBNAME="<%= @database_name %>"
CGIMAP_USERNAME="apis"
CGIMAP_MEMCACHE="127.0.0.1"
CGIMAP_RATELIMIT="204800"
CGIMAP_MAXDEBT="250"
+CGIMAP_MAP_AREA="<%= node[:web][:max_request_area] %>"
+CGIMAP_MAP_NODES"<%= node[:web][:max_number_of_nodes] %>"
+CGIMAP_MAX_WAY_NODES="<%= node[:web][:max_number_of_way_nodes] %>"
+CGIMAP_MAX_RELATION_MEMBERS="<%= node[:web][:max_number_of_relation_members] %>"
+CGIMAP_RATELIMIT_UPLOAD="true"
+<% Hash(@options).each do |name, value| -%>
+CGIMAP_<%= name.to_s.upcase %>="<%= value %>"
+<% end -%>
<html>
-<body>
-You've reached errol, the OpenStreetMap dev server. <br />
-<dl>
-<dt>If you are a user...</dt>
-<dd>You probably want <a href="https://www.openstreetmap.org/">OpenStreetMap</a> itself.</dd>
-<dt>If you are a developer...</dt>
-<dd>You might be interested in <a href="https://apis.dev.openstreetmap.org/">live instances</a> of various <a href="https://github.com/openstreetmap/openstreetmap-website#readme">Rails Port</a> code branches for testing clients against.</dd>
-</body>
+ <body>
+ <h4>
+ You've reached <a href="https://hardware.openstreetmap.org/servers/faffy.openstreetmap.org/">faffy</a>, the OpenStreetMap dev server.
+ </h4>
+ <dl>
+ <dt>If you are a user...</dt>
+ <dd>
+ You probably want
+ <a href="https://www.openstreetmap.org/">OpenStreetMap</a> itself.
+ </dd>
+ <dt>If you are a developer...</dt>
+ <dd>
+ You might be interested in
+ <a href="https://apis.dev.openstreetmap.org/">live instances</a> of
+ various
+ <a href="https://github.com/openstreetmap/openstreetmap-website#readme">Rails Port</a>
+ code branches for testing clients against.
+ </dd>
+ <dt>Request an account</dt>
+ <dd>
+ Anyone who wants to work on OpenStreetMap-related projects can
+ <a href="https://github.com/openstreetmap/operations/issues/new?assignees=Firefishy&labels=faffy%2Cuser+request&template=ACCOUNT-REQUEST.yml&title=%5BAccount+request%5D%3A+">request an account</a>
+ on the dev server.
+ </dd>
+ </dl>
+ </body>
</html>
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+RAILS_ENV="production"
+SLEEP_DELAY="60"
+SECRET_KEY_BASE="<%= @secret_key_base %>"
OpenStreetMap::Application.config.after_initialize do
- if ActiveRecord::Base.connection.table_exists?(:client_applications)
- unless webmaster = User.find_by_email("webmaster@openstreetmap.org")
- webmaster = User.new
- webmaster.display_name = "OpenStreetMap Webmaster"
- webmaster.email = "webmaster@openstreetmap.org"
- webmaster.pass_crypt = SecureRandom.hex
- webmaster.status = "active"
- webmaster.save!
- end
+ unless webmaster = User.find_by_email("webmaster@openstreetmap.org")
+ webmaster = User.new
+ webmaster.display_name = "OpenStreetMap Webmaster"
+ webmaster.email = "webmaster@openstreetmap.org"
+ webmaster.pass_crypt = SecureRandom.hex
+ webmaster.activate
+ webmaster.save!
+ end
+ if ActiveRecord::Base.connection.table_exists?(:client_applications)
unless id = webmaster.client_applications.find_by_name("iD")
id = webmaster.client_applications.new
id.name = "iD"
OAUTH_KEY = website.key
end
end
+
+ if ActiveRecord::Base.connection.table_exists?(:oauth_applications)
+ unless id = webmaster.oauth2_applications.find_by_name("iD")
+ id = webmaster.oauth2_applications.new
+ id.name = "iD"
+ id.redirect_uri = "https://<%= @site %>/id"
+ id.scopes = Oauth.scopes.map(&:name)
+ id.confidential = true
+ id.save!
+ end
+
+ if Kernel.const_defined?("Settings")
+ Settings.id_application = id.uid
+ else
+ ID_APPLICATION = id.uid
+ end
+
+ unless website = webmaster.oauth2_applications.find_by_name("Web Site")
+ website = webmaster.oauth2_applications.new
+ website.name = "Web Site"
+ website.redirect_uri = "https://<%= @site %>/"
+ website.scopes = Oauth.scopes.map(&:name)
+ website.confidential = true
+ website.save!
+ end
+
+ if Kernel.const_defined?("Settings")
+ Settings.oauth_application = website.uid
+ else
+ OAUTH_APPLICATION = website.uid
+ end
+ end
end
--- /dev/null
+[Slice]
+MemoryHigh=80%
+MemoryMax=90%
mode "644"
notifies :run, "execute[udevadm-trigger]"
end
+
+template "/etc/modprobe.d/nvme.conf" do
+ source "nvme.conf.erb"
+ owner "root"
+ group "root"
+ mode "644"
+ only_if { ::File.exist?("/sys/module/nvme/parameters/poll_queues") }
+end
+
+package "initramfs-tools"
+
+execute "update-initramfs" do
+ action :nothing
+ command "/usr/sbin/update-initramfs -u"
+ subscribes :run, "template[/etc/modprobe.d/nvme.conf]"
+end
# DO NOT EDIT - This file is being maintained by Chef
-[ipmi_*]
-timeout 10
+options nvme poll_queues=4
# Ethernet controller: Intel Corporation Ethernet Connection X722 for 10GBASE-T
SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x8086", ATTRS{device}=="0x37d2", RUN+="/sbin/ethtool -G $name rx 4096 tx 4096"
+# Disable Firmware Based LLDP handler
+SUBSYSTEM=="net", ACTION=="add", ENV{INTERFACE}=="*", DRIVERS=="i40e", RUN+="/sbin/ethtool --set-priv-flags $name disable-fw-lldp on"
+
# Workaround unreliable Western Digital WD RE3/RE4 disks (ATA only)
# Set sufficent Linux subsystem timeout and fix severe NCQ performance issue
ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata", ENV{ID_MODEL}=="WDC_WD5002ABYS-02B1B0", ATTR{device/timeout}="90", ATTR{device/queue_depth}="1", ATTR{queue/nr_requests}="256"
include_recipe "networking"
-package "isc-dhcp-server"
+package %w[
+ isc-dhcp-server
+ tftpd-hpa
+]
+
+service "tftpd-hpa" do
+ action [:enable, :start]
+ supports :status => true, :restart => true
+end
+
+remote_file "/srv/tftp/netboot.xyz.efi" do
+ action :create
+ source "https://boot.netboot.xyz/ipxe/netboot.xyz.efi"
+ owner "root"
+ group "root"
+ mode "644"
+end
+
+remote_file "/srv/tftp/netboot.xyz-snp.efi" do
+ action :create
+ source "https://boot.netboot.xyz/ipxe/netboot.xyz-snp.efi"
+ owner "root"
+ group "root"
+ mode "644"
+end
+
+remote_file "/srv/tftp/netboot.xyz.kpxe" do
+ action :create
+ source "https://boot.netboot.xyz/ipxe/netboot.xyz.kpxe"
+ owner "root"
+ group "root"
+ mode "644"
+end
domain = "#{node[:networking][:roles][:external][:zone]}.openstreetmap.org"
variables :domain => domain
end
+template "/etc/default/isc-dhcp-server" do
+ source "default.erb"
+ owner "root"
+ group "root"
+ mode "644"
+end
+
service "isc-dhcp-server" do
action [:enable, :start]
supports :status => true, :restart => true
subscribes :restart, "template[/etc/dhcp/dhcpd.conf]"
+ subscribes :restart, "template[/etc/default/isc-dhcp-server]"
+end
+
+service "isc-dhcp-server6" do
+ action [:disable, :stop]
end
--- /dev/null
+# Defaults for isc-dhcp-server (sourced by /etc/init.d/isc-dhcp-server)
+
+# Path to dhcpd's config file (default: /etc/dhcp/dhcpd.conf).
+#DHCPDv4_CONF=/etc/dhcp/dhcpd.conf
+#DHCPDv6_CONF=/etc/dhcp/dhcpd6.conf
+
+# Path to dhcpd's PID file (default: /var/run/dhcpd.pid).
+#DHCPDv4_PID=/var/run/dhcpd.pid
+#DHCPDv6_PID=/var/run/dhcpd6.pid
+
+# Additional options to start dhcpd with.
+# Don't use options -cf or -pf here; use DHCPD_CONF/ DHCPD_PID instead
+#OPTIONS=""
+
+# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
+# Separate multiple interfaces with spaces, e.g. "eth0 eth1".
+INTERFACESv4="<%= node.interfaces(:role => :internal).map { |i| i[:interface] }.join(" ") %>"
+INTERFACESv6=""
# DO NOT EDIT - This file is being maintained by Chef
+option arch code 93 = unsigned integer 16;
+# ilo5 expects TZ data per rfc4833
+option PCode code 100 = text;
+option TCode code 101 = text;
+
default-lease-time 600;
max-lease-time 7200;
-<% node.interfaces(:role => :internal).each do |interface| -%>
+<% node.ipaddresses(:role => :internal, :family => :inet).each do |address| -%>
-subnet <%= interface[:network] %> netmask <%= interface[:netmask] %> {
+subnet <%= address.network %> netmask <%= address.netmask %> {
authoritative;
range dynamic-bootp <%= node[:dhcpd][:first_address] %> <%= node[:dhcpd][:last_address] %>;
- # option broadcast-address <%= interface[:broadcast] %>;
- option routers <%= interface[:gateway] %>;
+ option routers <%= address.gateway %>;
option domain-name "<%= @domain %>";
- option domain-name-servers <%= interface[:gateway] %>;
- option ntp-servers <%= node[:ntp][:servers].first %>;
+ option domain-name-servers <%= address.gateway %>;
+ option ntp-servers <%= node[:ntp][:servers].join(", ") %>;
+
+ option time-offset 0;
+ option PCode "UTC0";
+ option TCode "Etc/UTC";
+
+ next-server <%= address.gateway %>;
+
+ # See https://netboot.xyz/docs/docker/#dhcp-configurations
+ if exists user-class and ( option user-class = "iPXE" ) {
+ filename "http://boot.netboot.xyz/menu.ipxe";
+ } elsif option arch = encode-int ( 16, 16 ) {
+ filename "http://boot.netboot.xyz/ipxe/netboot.xyz.efi";
+ option vendor-class-identifier "HTTPClient";
+ } elsif option arch = 00:07 {
+ filename "netboot.xyz.efi";
+ } else {
+ filename "netboot.xyz.kpxe";
+ }
}
<% end -%>
+host oob1.ams.openstreetmap.org {
+ hardware ethernet ea:e4:8e:c2:5b:19;
+ server-name "oob1.ams.openstreetmap.org";
+ fixed-address oob1.ams.openstreetmap.org;
+}
+
host pdu1.ams.openstreetmap.org {
hardware ethernet 00:c0:b7:e3:e8:f2;
server-name "pdu1.ams.openstreetmap.org";
fixed-address pdu2.ams.openstreetmap.org;
}
+host oob1.dub.openstreetmap.org {
+ hardware ethernet 62:bd:62:a6:05:25;
+ server-name "oob1.dub.openstreetmap.org";
+ fixed-address oob1.dub.openstreetmap.org;
+}
+
+host pdu1.dub.openstreetmap.org {
+ hardware ethernet 28:29:86:48:f7:f5;
+ server-name "pdu1.dub.openstreetmap.org";
+ fixed-address pdu1.dub.openstreetmap.org;
+}
+
+host pdu2.dub.openstreetmap.org {
+ hardware ethernet 28:29:86:48:f8:64;
+ server-name "pdu2.dub.openstreetmap.org";
+ fixed-address pdu2.dub.openstreetmap.org;
+}
+
host clifford.oob.openstreetmap.org {
hardware ethernet 1c:c1:de:78:20:d6;
server-name "clifford.oob.openstreetmap.org";
fixed-address clifford.oob.openstreetmap.org;
}
-host draco.oob.openstreetmap.org {
- hardware ethernet 9c:8e:99:25:99:7d;
- server-name "draco.oob.openstreetmap.org";
- fixed-address draco.oob.openstreetmap.org;
+host culebre.oob.openstreetmap.org {
+ hardware ethernet 3c:ec:ef:2f:29:41;
+ server-name "culebre.oob.openstreetmap.org";
+ fixed-address culebre.oob.openstreetmap.org;
+}
+
+host dribble.oob.openstreetmap.org {
+ hardware ethernet 80:30:e0:3e:e0:a0;
+ server-name "dribble.oob.openstreetmap.org";
+ fixed-address dribble.oob.openstreetmap.org;
}
host dulcy.oob.openstreetmap.org {
fixed-address eddie.oob.openstreetmap.org;
}
-host errol.oob.openstreetmap.org {
- hardware ethernet 00:e0:81:c0:8d:01;
- server-name "errol.oob.openstreetmap.org";
- fixed-address errol.oob.openstreetmap.org;
+host faffy.oob.openstreetmap.org {
+ hardware ethernet 98:f2:b3:21:f6:e2;
+ server-name "faffy.oob.openstreetmap.org";
+ fixed-address faffy.oob.openstreetmap.org;
}
-host eustace.oob.openstreetmap.org {
- hardware ethernet 1c:c1:de:71:4d:2e;
- server-name "eustace.oob.openstreetmap.org";
- fixed-address eustace.oob.openstreetmap.org;
+host fafnir.oob.openstreetmap.org {
+ hardware ethernet 38:63:bb:39:f0:96;
+ server-name "fafnir.oob.openstreetmap.org";
+ fixed-address fafnir.oob.openstreetmap.org;
}
-host grindtooth.oob.openstreetmap.org {
- hardware ethernet 98:4b:e1:6d:77:85;
- server-name "grindtooth.oob.openstreetmap.org";
- fixed-address grindtooth.oob.openstreetmap.org;
+host fume.oob.openstreetmap.org {
+ hardware ethernet 54:80:28:67:5e:31;
+ server-name "fume.oob.openstreetmap.org";
+ fixed-address fume.oob.openstreetmap.org;
+}
+
+host grisu.oob.openstreetmap.org {
+ hardware ethernet 54:80:28:67:61:03;
+ server-name "grisu.oob.openstreetmap.org";
+ fixed-address grisu.oob.openstreetmap.org;
+}
+
+host horntail.oob.openstreetmap.org {
+ hardware ethernet 3c:ec:ef:82:ac:d2;
+ server-name "horntail.oob.openstreetmap.org";
+ fixed-address horntail.oob.openstreetmap.org;
+}
+
+host idris.oob.openstreetmap.org {
+ hardware ethernet 94:57:a5:50:b5:a0;
+ server-name "idris.oob.openstreetmap.org";
+ fixed-address idris.oob.openstreetmap.org;
}
host ironbelly.oob.openstreetmap.org {
fixed-address ironbelly.oob.openstreetmap.org;
}
+host jakelong.oob.openstreetmap.org {
+ hardware ethernet d8:9d:67:66:02:9e;
+ server-name "jakelong.oob.openstreetmap.org";
+ fixed-address jakelong.oob.openstreetmap.org;
+}
+
host karm.oob.openstreetmap.org {
hardware ethernet 0c:c4:7a:67:cf:c4;
server-name "karm.oob.openstreetmap.org";
fixed-address karm.oob.openstreetmap.org;
}
-host lockheed.oob.openstreetmap.org {
- hardware ethernet 44:1e:a1:57:8f:fe;
- server-name "lockheed.oob.openstreetmap.org";
- fixed-address lockheed.oob.openstreetmap.org;
+host konqi.oob.openstreetmap.org {
+ hardware ethernet ec:b1:d7:7a:ea:64;
+ server-name "konqi.oob.openstreetmap.org";
+ fixed-address konqi.oob.openstreetmap.org;
+}
+
+host longma.oob.openstreetmap.org {
+ hardware ethernet 3c:ec:ef:2f:6d:4e;
+ server-name "longma.oob.openstreetmap.org";
+ fixed-address longma.oob.openstreetmap.org;
+}
+
+host muirdris.oob.openstreetmap.org {
+ hardware ethernet 80:30:e0:3e:f0:2a;
+ server-name "muirdris.oob.openstreetmap.org";
+ fixed-address muirdris.oob.openstreetmap.org;
+}
+
+host naga.oob.openstreetmap.org {
+ hardware ethernet 94:57:a5:5f:11:f2;
+ server-name "naga.oob.openstreetmap.org";
+ fixed-address naga.oob.openstreetmap.org;
}
host noquiklos.oob.openstreetmap.org {
fixed-address noquiklos.oob.openstreetmap.org;
}
+host norbert.oob.openstreetmap.org {
+ hardware ethernet 3c:ec:ef:82:ac:cf;
+ server-name "norbert.oob.openstreetmap.org";
+ fixed-address norbert.oob.openstreetmap.org;
+}
+
host odin.oob.openstreetmap.org {
hardware ethernet ac:1f:6b:c0:59:a3;
server-name "odin.oob.openstreetmap.org";
fixed-address odin.oob.openstreetmap.org;
}
-host orm.oob.openstreetmap.org {
- hardware ethernet 00:e0:81:c5:26:80;
- server-name "orm.oob.openstreetmap.org";
- fixed-address orm.oob.openstreetmap.org;
-}
-
-host ouroboros.oob.openstreetmap.org {
- hardware ethernet d4:85:64:4c:3d:00;
- server-name "ouroboros.oob.openstreetmap.org";
- fixed-address ouroboros.oob.openstreetmap.org;
-}
-
host pummelzacken.oob.openstreetmap.org {
hardware ethernet 00:25:90:cf:72:73;
server-name "pummelzacken.oob.openstreetmap.org";
fixed-address pummelzacken.oob.openstreetmap.org;
}
-host ramoth.oob.openstreetmap.org {
- hardware ethernet 0c:c4:7a:af:75:eb;
- server-name "ramoth.oob.openstreetmap.org";
- fixed-address ramoth.oob.openstreetmap.org;
-}
-
host ridley.oob.openstreetmap.org {
hardware ethernet d4:85:64:52:2d:d8;
server-name "ridley.oob.openstreetmap.org";
fixed-address snap-02.oob.openstreetmap.org;
}
+host snap-03.oob.openstreetmap.org {
+ hardware ethernet 3c:ec:ef:82:ab:f2;
+ server-name "snap-03.oob.openstreetmap.org";
+ fixed-address snap-03.oob.openstreetmap.org;
+}
+
host smaug.oob.openstreetmap.org {
- hardware ethernet 00:30:48:9d:57:ff;
+ hardware ethernet 80:30:e0:3e:d0:62;
server-name "smaug.oob.openstreetmap.org";
fixed-address smaug.oob.openstreetmap.org;
}
host spike-01.oob.openstreetmap.org {
- hardware ethernet 1c:c1:de:e8:1a:1c;
+ hardware ethernet 3c:a8:2a:11:78:d6;
server-name "spike-01.oob.openstreetmap.org";
fixed-address spike-01.oob.openstreetmap.org;
}
host spike-02.oob.openstreetmap.org {
- hardware ethernet 68:b5:99:af:d6:9c;
+ hardware ethernet 14:58:d0:5d:74:44;
server-name "spike-02.oob.openstreetmap.org";
fixed-address spike-02.oob.openstreetmap.org;
}
host spike-03.oob.openstreetmap.org {
- hardware ethernet 1c:c1:de:79:61:98;
+ hardware ethernet 38:63:bb:3a:b0:ce;
server-name "spike-03.oob.openstreetmap.org";
fixed-address spike-03.oob.openstreetmap.org;
}
fixed-address thorn-03.oob.openstreetmap.org;
}
-host urmel.oob.openstreetmap.org {
- hardware ethernet 1c:c1:de:e7:4d:b2;
- server-name "urmel.oob.openstreetmap.org";
- fixed-address urmel.oob.openstreetmap.org;
+host vhagar.oob.openstreetmap.org {
+ hardware ethernet 80:30:e0:3e:11:a0;
+ server-name "vhagar.oob.openstreetmap.org";
+ fixed-address vhagar.oob.openstreetmap.org;
}
host ysera.oob.openstreetmap.org {
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Base class for all HTML classes
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_Common
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @copyright 2001-2009 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id: Common.php,v 1.15 2009/04/03 15:26:22 avb Exp $
- * @link http://pear.php.net/package/HTML_Common/
- */
-
-/**
- * Base class for all HTML classes
- *
- * @category HTML
- * @package HTML_Common
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @version Release: 1.2.5
- * @abstract
- */
-class HTML_Common
-{
- /**
- * Associative array of attributes
- * @var array
- * @access private
- */
- var $_attributes = array();
-
- /**
- * Tab offset of the tag
- * @var int
- * @access private
- */
- var $_tabOffset = 0;
-
- /**
- * Tab string
- * @var string
- * @since 1.7
- * @access private
- */
- var $_tab = "\11";
-
- /**
- * Contains the line end string
- * @var string
- * @since 1.7
- * @access private
- */
- var $_lineEnd = "\12";
-
- /**
- * HTML comment on the object
- * @var string
- * @since 1.5
- * @access private
- */
- var $_comment = '';
-
- /**
- * Class constructor
- * @param mixed $attributes Associative array of table tag attributes
- * or HTML attributes name="value" pairs
- * @param int $tabOffset Indent offset in tabs
- * @access public
- */
- function HTML_Common($attributes = null, $tabOffset = 0)
- {
- $this->setAttributes($attributes);
- $this->setTabOffset($tabOffset);
- } // end constructor
-
- /**
- * Returns the current API version
- * @access public
- * @returns double
- */
- function apiVersion()
- {
- return 1.7;
- } // end func apiVersion
-
- /**
- * Returns the lineEnd
- *
- * @since 1.7
- * @access private
- * @return string
- */
- function _getLineEnd()
- {
- return $this->_lineEnd;
- } // end func getLineEnd
-
- /**
- * Returns a string containing the unit for indenting HTML
- *
- * @since 1.7
- * @access private
- * @return string
- */
- function _getTab()
- {
- return $this->_tab;
- } // end func _getTab
-
- /**
- * Returns a string containing the offset for the whole HTML code
- *
- * @return string
- * @access private
- */
- function _getTabs()
- {
- return str_repeat($this->_getTab(), $this->_tabOffset);
- } // end func _getTabs
-
- /**
- * Returns an HTML formatted attribute string
- * @param array $attributes
- * @return string
- * @access private
- */
- function _getAttrString($attributes)
- {
- $strAttr = '';
-
- if (is_array($attributes)) {
- $charset = HTML_Common::charset();
- foreach ($attributes as $key => $value) {
- $strAttr .= ' ' . $key . '="' . htmlspecialchars($value, ENT_COMPAT, $charset) . '"';
- }
- }
- return $strAttr;
- } // end func _getAttrString
-
- /**
- * Returns a valid atrributes array from either a string or array
- * @param mixed $attributes Either a typical HTML attribute string or an associative array
- * @access private
- * @return array
- */
- function _parseAttributes($attributes)
- {
- if (is_array($attributes)) {
- $ret = array();
- foreach ($attributes as $key => $value) {
- if (is_int($key)) {
- $key = $value = strtolower($value);
- } else {
- $key = strtolower($key);
- }
- $ret[$key] = $value;
- }
- return $ret;
-
- } elseif (is_string($attributes)) {
- $preg = "/(([A-Za-z_:]|[^\\x00-\\x7F])([A-Za-z0-9_:.-]|[^\\x00-\\x7F])*)" .
- "([ \\n\\t\\r]+)?(=([ \\n\\t\\r]+)?(\"[^\"]*\"|'[^']*'|[^ \\n\\t\\r]*))?/";
- if (preg_match_all($preg, $attributes, $regs)) {
- for ($counter=0; $counter<count($regs[1]); $counter++) {
- $name = $regs[1][$counter];
- $check = $regs[0][$counter];
- $value = $regs[7][$counter];
- if (trim($name) == trim($check)) {
- $arrAttr[strtolower(trim($name))] = strtolower(trim($name));
- } else {
- if (substr($value, 0, 1) == "\"" || substr($value, 0, 1) == "'") {
- $arrAttr[strtolower(trim($name))] = substr($value, 1, -1);
- } else {
- $arrAttr[strtolower(trim($name))] = trim($value);
- }
- }
- }
- return $arrAttr;
- }
- }
- } // end func _parseAttributes
-
- /**
- * Returns the array key for the given non-name-value pair attribute
- *
- * @param string $attr Attribute
- * @param array $attributes Array of attribute
- * @since 1.0
- * @access private
- * @return bool
- */
- function _getAttrKey($attr, $attributes)
- {
- if (isset($attributes[strtolower($attr)])) {
- return true;
- } else {
- return null;
- }
- } //end func _getAttrKey
-
- /**
- * Updates the attributes in $attr1 with the values in $attr2 without changing the other existing attributes
- * @param array $attr1 Original attributes array
- * @param array $attr2 New attributes array
- * @access private
- */
- function _updateAttrArray(&$attr1, $attr2)
- {
- if (!is_array($attr2)) {
- return false;
- }
- foreach ($attr2 as $key => $value) {
- $attr1[$key] = $value;
- }
- } // end func _updateAtrrArray
-
- /**
- * Removes the given attribute from the given array
- *
- * @param string $attr Attribute name
- * @param array $attributes Attribute array
- * @since 1.4
- * @access private
- * @return void
- */
- function _removeAttr($attr, &$attributes)
- {
- $attr = strtolower($attr);
- if (isset($attributes[$attr])) {
- unset($attributes[$attr]);
- }
- } //end func _removeAttr
-
- /**
- * Returns the value of the given attribute
- *
- * @param string $attr Attribute name
- * @since 1.5
- * @access public
- * @return string|null returns null if an attribute does not exist
- */
- function getAttribute($attr)
- {
- $attr = strtolower($attr);
- if (isset($this->_attributes[$attr])) {
- return $this->_attributes[$attr];
- }
- return null;
- } //end func getAttribute
-
- /**
- * Sets the value of the attribute
- *
- * @param string Attribute name
- * @param string Attribute value (will be set to $name if omitted)
- * @access public
- */
- function setAttribute($name, $value = null)
- {
- $name = strtolower($name);
- if (is_null($value)) {
- $value = $name;
- }
- $this->_attributes[$name] = $value;
- } // end func setAttribute
-
- /**
- * Sets the HTML attributes
- * @param mixed $attributes Either a typical HTML attribute string or an associative array
- * @access public
- */
- function setAttributes($attributes)
- {
- $this->_attributes = $this->_parseAttributes($attributes);
- } // end func setAttributes
-
- /**
- * Returns the assoc array (default) or string of attributes
- *
- * @param bool Whether to return the attributes as string
- * @since 1.6
- * @access public
- * @return mixed attributes
- */
- function getAttributes($asString = false)
- {
- if ($asString) {
- return $this->_getAttrString($this->_attributes);
- } else {
- return $this->_attributes;
- }
- } //end func getAttributes
-
- /**
- * Updates the passed attributes without changing the other existing attributes
- * @param mixed $attributes Either a typical HTML attribute string or an associative array
- * @access public
- */
- function updateAttributes($attributes)
- {
- $this->_updateAttrArray($this->_attributes, $this->_parseAttributes($attributes));
- } // end func updateAttributes
-
- /**
- * Removes an attribute
- *
- * @param string $attr Attribute name
- * @since 1.4
- * @access public
- * @return void
- */
- function removeAttribute($attr)
- {
- $this->_removeAttr($attr, $this->_attributes);
- } //end func removeAttribute
-
- /**
- * Sets the line end style to Windows, Mac, Unix or a custom string.
- *
- * @param string $style "win", "mac", "unix" or custom string.
- * @since 1.7
- * @access public
- * @return void
- */
- function setLineEnd($style)
- {
- switch ($style) {
- case 'win':
- $this->_lineEnd = "\15\12";
- break;
- case 'unix':
- $this->_lineEnd = "\12";
- break;
- case 'mac':
- $this->_lineEnd = "\15";
- break;
- default:
- $this->_lineEnd = $style;
- }
- } // end func setLineEnd
-
- /**
- * Sets the tab offset
- *
- * @param int $offset
- * @access public
- */
- function setTabOffset($offset)
- {
- $this->_tabOffset = $offset;
- } // end func setTabOffset
-
- /**
- * Returns the tabOffset
- *
- * @since 1.5
- * @access public
- * @return int
- */
- function getTabOffset()
- {
- return $this->_tabOffset;
- } //end func getTabOffset
-
- /**
- * Sets the string used to indent HTML
- *
- * @since 1.7
- * @param string $string String used to indent ("\11", "\t", ' ', etc.).
- * @access public
- * @return void
- */
- function setTab($string)
- {
- $this->_tab = $string;
- } // end func setTab
-
- /**
- * Sets the HTML comment to be displayed at the beginning of the HTML string
- *
- * @param string
- * @since 1.4
- * @access public
- * @return void
- */
- function setComment($comment)
- {
- $this->_comment = $comment;
- } // end func setHtmlComment
-
- /**
- * Returns the HTML comment
- *
- * @since 1.5
- * @access public
- * @return string
- */
- function getComment()
- {
- return $this->_comment;
- } //end func getComment
-
- /**
- * Abstract method. Must be extended to return the objects HTML
- *
- * @access public
- * @return string
- * @abstract
- */
- function toHtml()
- {
- return '';
- } // end func toHtml
-
- /**
- * Displays the HTML to the screen
- *
- * @access public
- */
- function display()
- {
- print $this->toHtml();
- } // end func display
-
- /**
- * Sets the charset to use by htmlspecialchars() function
- *
- * Since this parameter is expected to be global, the function is designed
- * to be called statically:
- * <code>
- * HTML_Common::charset('utf-8');
- * </code>
- * or
- * <code>
- * $charset = HTML_Common::charset();
- * </code>
- *
- * @param string New charset to use. Omit if just getting the
- * current value. Consult the htmlspecialchars() docs
- * for a list of supported character sets.
- * @return string Current charset
- * @access public
- * @static
- */
- function charset($newCharset = null)
- {
- static $charset = 'ISO-8859-1';
-
- if (!is_null($newCharset)) {
- $charset = $newCharset;
- }
- return $charset;
- } // end func charset
-} // end class HTML_Common
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Create, validate and process HTML forms
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Alexey Borzov <avb@php.net>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * PEAR and PEAR_Error classes, for error handling
- */
-require_once 'PEAR.php';
-/**
- * Base class for all HTML classes
- */
-require_once 'HTML/Common.php';
-/**
- * Static utility methods
- */
-require_once 'HTML/QuickForm/utils.php';
-
-/**
- * Element types known to HTML_QuickForm
- * @see HTML_QuickForm::registerElementType(), HTML_QuickForm::getRegisteredTypes(),
- * HTML_QuickForm::isTypeRegistered()
- * @global array $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES']
- */
-$GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'] =
- array(
- 'group' =>array('HTML/QuickForm/group.php','HTML_QuickForm_group'),
- 'hidden' =>array('HTML/QuickForm/hidden.php','HTML_QuickForm_hidden'),
- 'reset' =>array('HTML/QuickForm/reset.php','HTML_QuickForm_reset'),
- 'checkbox' =>array('HTML/QuickForm/checkbox.php','HTML_QuickForm_checkbox'),
- 'file' =>array('HTML/QuickForm/file.php','HTML_QuickForm_file'),
- 'image' =>array('HTML/QuickForm/image.php','HTML_QuickForm_image'),
- 'password' =>array('HTML/QuickForm/password.php','HTML_QuickForm_password'),
- 'radio' =>array('HTML/QuickForm/radio.php','HTML_QuickForm_radio'),
- 'button' =>array('HTML/QuickForm/button.php','HTML_QuickForm_button'),
- 'submit' =>array('HTML/QuickForm/submit.php','HTML_QuickForm_submit'),
- 'select' =>array('HTML/QuickForm/select.php','HTML_QuickForm_select'),
- 'hiddenselect' =>array('HTML/QuickForm/hiddenselect.php','HTML_QuickForm_hiddenselect'),
- 'text' =>array('HTML/QuickForm/text.php','HTML_QuickForm_text'),
- 'textarea' =>array('HTML/QuickForm/textarea.php','HTML_QuickForm_textarea'),
- 'link' =>array('HTML/QuickForm/link.php','HTML_QuickForm_link'),
- 'advcheckbox' =>array('HTML/QuickForm/advcheckbox.php','HTML_QuickForm_advcheckbox'),
- 'date' =>array('HTML/QuickForm/date.php','HTML_QuickForm_date'),
- 'static' =>array('HTML/QuickForm/static.php','HTML_QuickForm_static'),
- 'header' =>array('HTML/QuickForm/header.php', 'HTML_QuickForm_header'),
- 'html' =>array('HTML/QuickForm/html.php', 'HTML_QuickForm_html'),
- 'hierselect' =>array('HTML/QuickForm/hierselect.php', 'HTML_QuickForm_hierselect'),
- 'autocomplete' =>array('HTML/QuickForm/autocomplete.php', 'HTML_QuickForm_autocomplete'),
- 'xbutton' =>array('HTML/QuickForm/xbutton.php','HTML_QuickForm_xbutton')
- );
-
-/**
- * Validation rules known to HTML_QuickForm
- * @see HTML_QuickForm::registerRule(), HTML_QuickForm::getRegisteredRules(),
- * HTML_QuickForm::isRuleRegistered()
- * @global array $GLOBALS['_HTML_QuickForm_registered_rules']
- */
-$GLOBALS['_HTML_QuickForm_registered_rules'] = array(
- 'required' => array('html_quickform_rule_required', 'HTML/QuickForm/Rule/Required.php'),
- 'maxlength' => array('html_quickform_rule_range', 'HTML/QuickForm/Rule/Range.php'),
- 'minlength' => array('html_quickform_rule_range', 'HTML/QuickForm/Rule/Range.php'),
- 'rangelength' => array('html_quickform_rule_range', 'HTML/QuickForm/Rule/Range.php'),
- 'email' => array('html_quickform_rule_email', 'HTML/QuickForm/Rule/Email.php'),
- 'regex' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'),
- 'lettersonly' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'),
- 'alphanumeric' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'),
- 'numeric' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'),
- 'nopunctuation' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'),
- 'nonzero' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'),
- 'callback' => array('html_quickform_rule_callback', 'HTML/QuickForm/Rule/Callback.php'),
- 'compare' => array('html_quickform_rule_compare', 'HTML/QuickForm/Rule/Compare.php')
-);
-
-// {{{ error codes
-
-/**#@+
- * Error codes for HTML_QuickForm
- *
- * Codes are mapped to textual messages by errorMessage() method, if you add a
- * new code be sure to add a new message for it to errorMessage()
- *
- * @see HTML_QuickForm::errorMessage()
- */
-define('QUICKFORM_OK', 1);
-define('QUICKFORM_ERROR', -1);
-define('QUICKFORM_INVALID_RULE', -2);
-define('QUICKFORM_NONEXIST_ELEMENT', -3);
-define('QUICKFORM_INVALID_FILTER', -4);
-define('QUICKFORM_UNREGISTERED_ELEMENT', -5);
-define('QUICKFORM_INVALID_ELEMENT_NAME', -6);
-define('QUICKFORM_INVALID_PROCESS', -7);
-define('QUICKFORM_DEPRECATED', -8);
-define('QUICKFORM_INVALID_DATASOURCE', -9);
-/**#@-*/
-
-// }}}
-
-/**
- * Create, validate and process HTML forms
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Alexey Borzov <avb@php.net>
- * @version Release: 3.2.16
- */
-class HTML_QuickForm extends HTML_Common
-{
- // {{{ properties
-
- /**
- * Array containing the form fields
- * @since 1.0
- * @var array
- * @access private
- */
- var $_elements = array();
-
- /**
- * Array containing element name to index map
- * @since 1.1
- * @var array
- * @access private
- */
- var $_elementIndex = array();
-
- /**
- * Array containing indexes of duplicate elements
- * @since 2.10
- * @var array
- * @access private
- */
- var $_duplicateIndex = array();
-
- /**
- * Array containing required field IDs
- * @since 1.0
- * @var array
- * @access private
- */
- var $_required = array();
-
- /**
- * Prefix message in javascript alert if error
- * @since 1.0
- * @var string
- * @access public
- */
- var $_jsPrefix = 'Invalid information entered.';
-
- /**
- * Postfix message in javascript alert if error
- * @since 1.0
- * @var string
- * @access public
- */
- var $_jsPostfix = 'Please correct these fields.';
-
- /**
- * Datasource object implementing the informal
- * datasource protocol
- * @since 3.3
- * @var object
- * @access private
- */
- var $_datasource;
-
- /**
- * Array of default form values
- * @since 2.0
- * @var array
- * @access private
- */
- var $_defaultValues = array();
-
- /**
- * Array of constant form values
- * @since 2.0
- * @var array
- * @access private
- */
- var $_constantValues = array();
-
- /**
- * Array of submitted form values
- * @since 1.0
- * @var array
- * @access private
- */
- var $_submitValues = array();
-
- /**
- * Array of submitted form files
- * @since 1.0
- * @var integer
- * @access public
- */
- var $_submitFiles = array();
-
- /**
- * Value for maxfilesize hidden element if form contains file input
- * @since 1.0
- * @var integer
- * @access public
- */
- var $_maxFileSize = 1048576; // 1 Mb = 1048576
-
- /**
- * Flag to know if all fields are frozen
- * @since 1.0
- * @var boolean
- * @access private
- */
- var $_freezeAll = false;
-
- /**
- * Array containing the form rules
- * @since 1.0
- * @var array
- * @access private
- */
- var $_rules = array();
-
- /**
- * Form rules, global variety
- * @var array
- * @access private
- */
- var $_formRules = array();
-
- /**
- * Array containing the validation errors
- * @since 1.0
- * @var array
- * @access private
- */
- var $_errors = array();
-
- /**
- * Note for required fields in the form
- * @var string
- * @since 1.0
- * @access private
- */
- var $_requiredNote = '<span style="font-size:80%; color:#ff0000;">*</span><span style="font-size:80%;"> denotes required field</span>';
-
- /**
- * Whether the form was submitted
- * @var boolean
- * @access private
- */
- var $_flagSubmitted = false;
-
- // }}}
- // {{{ constructor
-
- /**
- * Class constructor
- * @param string $formName Form's name.
- * @param string $method (optional)Form's method defaults to 'POST'
- * @param string $action (optional)Form's action
- * @param string $target (optional)Form's target defaults to '_self'
- * @param mixed $attributes (optional)Extra attributes for <form> tag
- * @param bool $trackSubmit (optional)Whether to track if the form was submitted by adding a special hidden field
- * @access public
- */
- function HTML_QuickForm($formName='', $method='post', $action='', $target='', $attributes=null, $trackSubmit = false)
- {
- HTML_Common::HTML_Common($attributes);
- $method = (strtoupper($method) == 'GET') ? 'get' : 'post';
- $action = ($action == '') ? $_SERVER['PHP_SELF'] : $action;
- $target = empty($target) ? array() : array('target' => $target);
- $attributes = array('action'=>$action, 'method'=>$method, 'name'=>$formName, 'id'=>$formName) + $target;
- $this->updateAttributes($attributes);
- if (!$trackSubmit || isset($_REQUEST['_qf__' . $formName])) {
- if (1 == get_magic_quotes_gpc()) {
- $this->_submitValues = $this->_recursiveFilter('stripslashes', 'get' == $method? $_GET: $_POST);
- foreach ($_FILES as $keyFirst => $valFirst) {
- foreach ($valFirst as $keySecond => $valSecond) {
- if ('name' == $keySecond) {
- $this->_submitFiles[$keyFirst][$keySecond] = $this->_recursiveFilter('stripslashes', $valSecond);
- } else {
- $this->_submitFiles[$keyFirst][$keySecond] = $valSecond;
- }
- }
- }
- } else {
- $this->_submitValues = 'get' == $method? $_GET: $_POST;
- $this->_submitFiles = $_FILES;
- }
- $this->_flagSubmitted = count($this->_submitValues) > 0 || count($this->_submitFiles) > 0;
- }
- if ($trackSubmit) {
- unset($this->_submitValues['_qf__' . $formName]);
- $this->addElement('hidden', '_qf__' . $formName, null);
- }
- if (preg_match('/^([0-9]+)([a-zA-Z]*)$/', ini_get('upload_max_filesize'), $matches)) {
- // see http://www.php.net/manual/en/faq.using.php#faq.using.shorthandbytes
- switch (strtoupper($matches['2'])) {
- case 'G':
- $this->_maxFileSize = $matches['1'] * 1073741824;
- break;
- case 'M':
- $this->_maxFileSize = $matches['1'] * 1048576;
- break;
- case 'K':
- $this->_maxFileSize = $matches['1'] * 1024;
- break;
- default:
- $this->_maxFileSize = $matches['1'];
- }
- }
- } // end constructor
-
- // }}}
- // {{{ apiVersion()
-
- /**
- * Returns the current API version
- *
- * @since 1.0
- * @access public
- * @return float
- */
- function apiVersion()
- {
- return 3.2;
- } // end func apiVersion
-
- // }}}
- // {{{ registerElementType()
-
- /**
- * Registers a new element type
- *
- * @param string $typeName Name of element type
- * @param string $include Include path for element type
- * @param string $className Element class name
- * @since 1.0
- * @access public
- * @return void
- */
- function registerElementType($typeName, $include, $className)
- {
- $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][strtolower($typeName)] = array($include, $className);
- } // end func registerElementType
-
- // }}}
- // {{{ registerRule()
-
- /**
- * Registers a new validation rule
- *
- * @param string $ruleName Name of validation rule
- * @param string $type Either: 'regex', 'function' or 'rule' for an HTML_QuickForm_Rule object
- * @param string $data1 Name of function, regular expression or HTML_QuickForm_Rule classname
- * @param string $data2 Object parent of above function or HTML_QuickForm_Rule file path
- * @since 1.0
- * @access public
- * @return void
- */
- function registerRule($ruleName, $type, $data1, $data2 = null)
- {
- include_once('HTML/QuickForm/RuleRegistry.php');
- $registry =& HTML_QuickForm_RuleRegistry::singleton();
- $registry->registerRule($ruleName, $type, $data1, $data2);
- } // end func registerRule
-
- // }}}
- // {{{ elementExists()
-
- /**
- * Returns true if element is in the form
- *
- * @param string $element form name of element to check
- * @since 1.0
- * @access public
- * @return boolean
- */
- function elementExists($element=null)
- {
- return isset($this->_elementIndex[$element]);
- } // end func elementExists
-
- // }}}
- // {{{ setDatasource()
-
- /**
- * Sets a datasource object for this form object
- *
- * Datasource default and constant values will feed the QuickForm object if
- * the datasource implements defaultValues() and constantValues() methods.
- *
- * @param object $datasource datasource object implementing the informal datasource protocol
- * @param mixed $defaultsFilter string or array of filter(s) to apply to default values
- * @param mixed $constantsFilter string or array of filter(s) to apply to constants values
- * @since 3.3
- * @access public
- * @return void
- * @throws HTML_QuickForm_Error
- */
- function setDatasource(&$datasource, $defaultsFilter = null, $constantsFilter = null)
- {
- if (is_object($datasource)) {
- $this->_datasource =& $datasource;
- if (is_callable(array($datasource, 'defaultValues'))) {
- $this->setDefaults($datasource->defaultValues($this), $defaultsFilter);
- }
- if (is_callable(array($datasource, 'constantValues'))) {
- $this->setConstants($datasource->constantValues($this), $constantsFilter);
- }
- } else {
- return PEAR::raiseError(null, QUICKFORM_INVALID_DATASOURCE, null, E_USER_WARNING, "Datasource is not an object in QuickForm::setDatasource()", 'HTML_QuickForm_Error', true);
- }
- } // end func setDatasource
-
- // }}}
- // {{{ setDefaults()
-
- /**
- * Initializes default form values
- *
- * @param array $defaultValues values used to fill the form
- * @param mixed $filter (optional) filter(s) to apply to all default values
- * @since 1.0
- * @access public
- * @return void
- * @throws HTML_QuickForm_Error
- */
- function setDefaults($defaultValues = null, $filter = null)
- {
- if (is_array($defaultValues)) {
- if (isset($filter)) {
- if (is_array($filter) && (2 != count($filter) || !is_callable($filter))) {
- foreach ($filter as $val) {
- if (!is_callable($val)) {
- return PEAR::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setDefaults()", 'HTML_QuickForm_Error', true);
- } else {
- $defaultValues = $this->_recursiveFilter($val, $defaultValues);
- }
- }
- } elseif (!is_callable($filter)) {
- return PEAR::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setDefaults()", 'HTML_QuickForm_Error', true);
- } else {
- $defaultValues = $this->_recursiveFilter($filter, $defaultValues);
- }
- }
- $this->_defaultValues = HTML_QuickForm::arrayMerge($this->_defaultValues, $defaultValues);
- foreach (array_keys($this->_elements) as $key) {
- $this->_elements[$key]->onQuickFormEvent('updateValue', null, $this);
- }
- }
- } // end func setDefaults
-
- // }}}
- // {{{ setConstants()
-
- /**
- * Initializes constant form values.
- * These values won't get overridden by POST or GET vars
- *
- * @param array $constantValues values used to fill the form
- * @param mixed $filter (optional) filter(s) to apply to all default values
- *
- * @since 2.0
- * @access public
- * @return void
- * @throws HTML_QuickForm_Error
- */
- function setConstants($constantValues = null, $filter = null)
- {
- if (is_array($constantValues)) {
- if (isset($filter)) {
- if (is_array($filter) && (2 != count($filter) || !is_callable($filter))) {
- foreach ($filter as $val) {
- if (!is_callable($val)) {
- return PEAR::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setConstants()", 'HTML_QuickForm_Error', true);
- } else {
- $constantValues = $this->_recursiveFilter($val, $constantValues);
- }
- }
- } elseif (!is_callable($filter)) {
- return PEAR::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setConstants()", 'HTML_QuickForm_Error', true);
- } else {
- $constantValues = $this->_recursiveFilter($filter, $constantValues);
- }
- }
- $this->_constantValues = HTML_QuickForm::arrayMerge($this->_constantValues, $constantValues);
- foreach (array_keys($this->_elements) as $key) {
- $this->_elements[$key]->onQuickFormEvent('updateValue', null, $this);
- }
- }
- } // end func setConstants
-
- // }}}
- // {{{ setMaxFileSize()
-
- /**
- * Sets the value of MAX_FILE_SIZE hidden element
- *
- * @param int $bytes Size in bytes
- * @since 3.0
- * @access public
- * @return void
- */
- function setMaxFileSize($bytes = 0)
- {
- if ($bytes > 0) {
- $this->_maxFileSize = $bytes;
- }
- if (!$this->elementExists('MAX_FILE_SIZE')) {
- $this->addElement('hidden', 'MAX_FILE_SIZE', $this->_maxFileSize);
- } else {
- $el =& $this->getElement('MAX_FILE_SIZE');
- $el->updateAttributes(array('value' => $this->_maxFileSize));
- }
- } // end func setMaxFileSize
-
- // }}}
- // {{{ getMaxFileSize()
-
- /**
- * Returns the value of MAX_FILE_SIZE hidden element
- *
- * @since 3.0
- * @access public
- * @return int max file size in bytes
- */
- function getMaxFileSize()
- {
- return $this->_maxFileSize;
- } // end func getMaxFileSize
-
- // }}}
- // {{{ &createElement()
-
- /**
- * Creates a new form element of the given type.
- *
- * This method accepts variable number of parameters, their
- * meaning and count depending on $elementType
- *
- * @param string $elementType type of element to add (text, textarea, file...)
- * @since 1.0
- * @access public
- * @return HTML_QuickForm_Element
- * @throws HTML_QuickForm_Error
- */
- function &createElement($elementType)
- {
- $args = func_get_args();
- $element =& HTML_QuickForm::_loadElement('createElement', $elementType, array_slice($args, 1), null);
- return $element;
- } // end func createElement
-
- // }}}
- // {{{ _loadElement()
-
- /**
- * Returns a form element of the given type
- *
- * @param string $event event to send to newly created element ('createElement' or 'addElement')
- * @param string $type element type
- * @param array $args arguments for event
- * @since 2.0
- * @access private
- * @return HTML_QuickForm_Element
- * @throws HTML_QuickForm_Error
- */
- function &_loadElement($event, $type, $args, $form)
- {
- $type = strtolower($type);
- if (!HTML_QuickForm::isTypeRegistered($type)) {
- $error = PEAR::raiseError(null, QUICKFORM_UNREGISTERED_ELEMENT, null, E_USER_WARNING, "Element '$type' does not exist in HTML_QuickForm::_loadElement()", 'HTML_QuickForm_Error', true);
- return $error;
- }
- $className = $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][$type][1];
- $includeFile = $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][$type][0];
- include_once($includeFile);
- $elementObject = new $className();
- for ($i = 0; $i < 5; $i++) {
- if (!isset($args[$i])) {
- $args[$i] = null;
- }
- }
- $err = $elementObject->onQuickFormEvent($event, $args, $form);
- if ($err !== true) {
- return $err;
- }
- return $elementObject;
- } // end func _loadElement
-
- // }}}
- // {{{ addElement()
-
- /**
- * Adds an element into the form
- *
- * If $element is a string representing element type, then this
- * method accepts variable number of parameters, their meaning
- * and count depending on $element
- *
- * @param mixed $element element object or type of element to add (text, textarea, file...)
- * @since 1.0
- * @return HTML_QuickForm_Element a reference to newly added element
- * @access public
- * @throws HTML_QuickForm_Error
- */
- function &addElement($element)
- {
- if (is_object($element) && is_subclass_of($element, 'html_quickform_element')) {
- $elementObject = &$element;
- $elementObject->onQuickFormEvent('updateValue', null, $this);
- } else {
- $args = func_get_args();
- $elementObject =& $this->_loadElement('addElement', $element, array_slice($args, 1), $this);
- if (PEAR::isError($elementObject)) {
- return $elementObject;
- }
- }
- $elementName = $elementObject->getName();
-
- // Add the element if it is not an incompatible duplicate
- if (!empty($elementName) && isset($this->_elementIndex[$elementName])) {
- if ($this->_elements[$this->_elementIndex[$elementName]]->getType() ==
- $elementObject->getType()) {
- $this->_elements[] =& $elementObject;
- $elKeys = array_keys($this->_elements);
- $this->_duplicateIndex[$elementName][] = end($elKeys);
- } else {
- $error = PEAR::raiseError(null, QUICKFORM_INVALID_ELEMENT_NAME, null, E_USER_WARNING, "Element '$elementName' already exists in HTML_QuickForm::addElement()", 'HTML_QuickForm_Error', true);
- return $error;
- }
- } else {
- $this->_elements[] =& $elementObject;
- $elKeys = array_keys($this->_elements);
- $this->_elementIndex[$elementName] = end($elKeys);
- }
- if ($this->_freezeAll) {
- $elementObject->freeze();
- }
-
- return $elementObject;
- } // end func addElement
-
- // }}}
- // {{{ insertElementBefore()
-
- /**
- * Inserts a new element right before the other element
- *
- * Warning: it is not possible to check whether the $element is already
- * added to the form, therefore if you want to move the existing form
- * element to a new position, you'll have to use removeElement():
- * $form->insertElementBefore($form->removeElement('foo', false), 'bar');
- *
- * @access public
- * @since 3.2.4
- * @param HTML_QuickForm_element Element to insert
- * @param string Name of the element before which the new
- * one is inserted
- * @return HTML_QuickForm_element reference to inserted element
- * @throws HTML_QuickForm_Error
- */
- function &insertElementBefore(&$element, $nameAfter)
- {
- if (!empty($this->_duplicateIndex[$nameAfter])) {
- $error = PEAR::raiseError(null, QUICKFORM_INVALID_ELEMENT_NAME, null, E_USER_WARNING, 'Several elements named "' . $nameAfter . '" exist in HTML_QuickForm::insertElementBefore().', 'HTML_QuickForm_Error', true);
- return $error;
- } elseif (!$this->elementExists($nameAfter)) {
- $error = PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$nameAfter' does not exist in HTML_QuickForm::insertElementBefore()", 'HTML_QuickForm_Error', true);
- return $error;
- }
- $elementName = $element->getName();
- $targetIdx = $this->_elementIndex[$nameAfter];
- $duplicate = false;
- // Like in addElement(), check that it's not an incompatible duplicate
- if (!empty($elementName) && isset($this->_elementIndex[$elementName])) {
- if ($this->_elements[$this->_elementIndex[$elementName]]->getType() != $element->getType()) {
- $error = PEAR::raiseError(null, QUICKFORM_INVALID_ELEMENT_NAME, null, E_USER_WARNING, "Element '$elementName' already exists in HTML_QuickForm::insertElementBefore()", 'HTML_QuickForm_Error', true);
- return $error;
- }
- $duplicate = true;
- }
- // Move all the elements after added back one place, reindex _elementIndex and/or _duplicateIndex
- $elKeys = array_keys($this->_elements);
- for ($i = end($elKeys); $i >= $targetIdx; $i--) {
- if (isset($this->_elements[$i])) {
- $currentName = $this->_elements[$i]->getName();
- $this->_elements[$i + 1] =& $this->_elements[$i];
- if ($this->_elementIndex[$currentName] == $i) {
- $this->_elementIndex[$currentName] = $i + 1;
- } else {
- $dupIdx = array_search($i, $this->_duplicateIndex[$currentName]);
- $this->_duplicateIndex[$currentName][$dupIdx] = $i + 1;
- }
- unset($this->_elements[$i]);
- }
- }
- // Put the element in place finally
- $this->_elements[$targetIdx] =& $element;
- if (!$duplicate) {
- $this->_elementIndex[$elementName] = $targetIdx;
- } else {
- $this->_duplicateIndex[$elementName][] = $targetIdx;
- }
- $element->onQuickFormEvent('updateValue', null, $this);
- if ($this->_freezeAll) {
- $element->freeze();
- }
- // If not done, the elements will appear in reverse order
- ksort($this->_elements);
- return $element;
- }
-
- // }}}
- // {{{ addGroup()
-
- /**
- * Adds an element group
- * @param array $elements array of elements composing the group
- * @param string $name (optional)group name
- * @param string $groupLabel (optional)group label
- * @param string $separator (optional)string to separate elements
- * @param string $appendName (optional)specify whether the group name should be
- * used in the form element name ex: group[element]
- * @return HTML_QuickForm_group reference to a newly added group
- * @since 2.8
- * @access public
- * @throws HTML_QuickForm_Error
- */
- function &addGroup($elements, $name=null, $groupLabel='', $separator=null, $appendName = true)
- {
- static $anonGroups = 1;
-
- if (0 == strlen($name)) {
- $name = 'qf_group_' . $anonGroups++;
- $appendName = false;
- }
- $group =& $this->addElement('group', $name, $groupLabel, $elements, $separator, $appendName);
- return $group;
- } // end func addGroup
-
- // }}}
- // {{{ &getElement()
-
- /**
- * Returns a reference to the element
- *
- * @param string $element Element name
- * @since 2.0
- * @access public
- * @return HTML_QuickForm_element reference to element
- * @throws HTML_QuickForm_Error
- */
- function &getElement($element)
- {
- if (isset($this->_elementIndex[$element])) {
- return $this->_elements[$this->_elementIndex[$element]];
- } else {
- $error = PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::getElement()", 'HTML_QuickForm_Error', true);
- return $error;
- }
- } // end func getElement
-
- // }}}
- // {{{ &getElementValue()
-
- /**
- * Returns the element's raw value
- *
- * This returns the value as submitted by the form (not filtered)
- * or set via setDefaults() or setConstants()
- *
- * @param string $element Element name
- * @since 2.0
- * @access public
- * @return mixed element value
- * @throws HTML_QuickForm_Error
- */
- function &getElementValue($element)
- {
- if (!isset($this->_elementIndex[$element])) {
- $error = PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::getElementValue()", 'HTML_QuickForm_Error', true);
- return $error;
- }
- $value = $this->_elements[$this->_elementIndex[$element]]->getValue();
- if (isset($this->_duplicateIndex[$element])) {
- foreach ($this->_duplicateIndex[$element] as $index) {
- if (null !== ($v = $this->_elements[$index]->getValue())) {
- if (is_array($value)) {
- $value[] = $v;
- } else {
- $value = (null === $value)? $v: array($value, $v);
- }
- }
- }
- }
- return $value;
- } // end func getElementValue
-
- // }}}
- // {{{ getSubmitValue()
-
- /**
- * Returns the elements value after submit and filter
- *
- * @param string Element name
- * @since 2.0
- * @access public
- * @return mixed submitted element value or null if not set
- */
- function getSubmitValue($elementName)
- {
- $value = null;
- if (isset($this->_submitValues[$elementName]) || isset($this->_submitFiles[$elementName])) {
- $value = isset($this->_submitValues[$elementName])? $this->_submitValues[$elementName]: array();
- if (is_array($value) && isset($this->_submitFiles[$elementName])) {
- foreach ($this->_submitFiles[$elementName] as $k => $v) {
- $value = HTML_QuickForm::arrayMerge($value, $this->_reindexFiles($this->_submitFiles[$elementName][$k], $k));
- }
- }
-
- } elseif ('file' == $this->getElementType($elementName)) {
- return $this->getElementValue($elementName);
-
- } elseif (false !== ($pos = strpos($elementName, '['))) {
- $base = str_replace(
- array('\\', '\''), array('\\\\', '\\\''),
- substr($elementName, 0, $pos)
- );
-
- $keys = str_replace(
- array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"),
- substr($elementName, $pos + 1, -1)
- );
- $idx = "['" . $keys . "']";
- $keyArray = explode("']['", $keys);
-
- if (isset($this->_submitValues[$base])) {
- $value = HTML_QuickForm_utils::recursiveValue($this->_submitValues[$base], $keyArray, NULL);
- }
-
- if ((is_array($value) || null === $value) && isset($this->_submitFiles[$base])) {
- $props = array('name', 'type', 'size', 'tmp_name', 'error');
- $code = "if (!isset(\$this->_submitFiles['{$base}']['name']{$idx})) {\n" .
- " return null;\n" .
- "} else {\n" .
- " \$v = array();\n";
- foreach ($props as $prop) {
- $code .= " \$v = HTML_QuickForm::arrayMerge(\$v, \$this->_reindexFiles(\$this->_submitFiles['{$base}']['{$prop}']{$idx}, '{$prop}'));\n";
- }
- $fileValue = eval($code . " return \$v;\n}\n");
- if (null !== $fileValue) {
- $value = null === $value? $fileValue: HTML_QuickForm::arrayMerge($value, $fileValue);
- }
- }
- }
-
- // This is only supposed to work for groups with appendName = false
- if (null === $value && 'group' == $this->getElementType($elementName)) {
- $group =& $this->getElement($elementName);
- $elements =& $group->getElements();
- foreach (array_keys($elements) as $key) {
- $name = $group->getElementName($key);
- // prevent endless recursion in case of radios and such
- if ($name != $elementName) {
- if (null !== ($v = $this->getSubmitValue($name))) {
- $value[$name] = $v;
- }
- }
- }
- }
- return $value;
- } // end func getSubmitValue
-
- // }}}
- // {{{ _reindexFiles()
-
- /**
- * A helper function to change the indexes in $_FILES array
- *
- * @param mixed Some value from the $_FILES array
- * @param string The key from the $_FILES array that should be appended
- * @return array
- */
- function _reindexFiles($value, $key)
- {
- if (!is_array($value)) {
- return array($key => $value);
- } else {
- $ret = array();
- foreach ($value as $k => $v) {
- $ret[$k] = $this->_reindexFiles($v, $key);
- }
- return $ret;
- }
- }
-
- // }}}
- // {{{ getElementError()
-
- /**
- * Returns error corresponding to validated element
- *
- * @param string $element Name of form element to check
- * @since 1.0
- * @access public
- * @return string error message corresponding to checked element
- */
- function getElementError($element)
- {
- if (isset($this->_errors[$element])) {
- return $this->_errors[$element];
- }
- } // end func getElementError
-
- // }}}
- // {{{ setElementError()
-
- /**
- * Set error message for a form element
- *
- * @param string $element Name of form element to set error for
- * @param string $message Error message, if empty then removes the current error message
- * @since 1.0
- * @access public
- * @return void
- */
- function setElementError($element, $message = null)
- {
- if (!empty($message)) {
- $this->_errors[$element] = $message;
- } else {
- unset($this->_errors[$element]);
- }
- } // end func setElementError
-
- // }}}
- // {{{ getElementType()
-
- /**
- * Returns the type of the given element
- *
- * @param string $element Name of form element
- * @since 1.1
- * @access public
- * @return string Type of the element, false if the element is not found
- */
- function getElementType($element)
- {
- if (isset($this->_elementIndex[$element])) {
- return $this->_elements[$this->_elementIndex[$element]]->getType();
- }
- return false;
- } // end func getElementType
-
- // }}}
- // {{{ updateElementAttr()
-
- /**
- * Updates Attributes for one or more elements
- *
- * @param mixed $elements Array of element names/objects or string of elements to be updated
- * @param mixed $attrs Array or sting of html attributes
- * @since 2.10
- * @access public
- * @return void
- */
- function updateElementAttr($elements, $attrs)
- {
- if (is_string($elements)) {
- $elements = preg_split('/[ ]?,[ ]?/', $elements);
- }
- foreach (array_keys($elements) as $key) {
- if (is_object($elements[$key]) && is_a($elements[$key], 'HTML_QuickForm_element')) {
- $elements[$key]->updateAttributes($attrs);
- } elseif (isset($this->_elementIndex[$elements[$key]])) {
- $this->_elements[$this->_elementIndex[$elements[$key]]]->updateAttributes($attrs);
- if (isset($this->_duplicateIndex[$elements[$key]])) {
- foreach ($this->_duplicateIndex[$elements[$key]] as $index) {
- $this->_elements[$index]->updateAttributes($attrs);
- }
- }
- }
- }
- } // end func updateElementAttr
-
- // }}}
- // {{{ removeElement()
-
- /**
- * Removes an element
- *
- * The method "unlinks" an element from the form, returning the reference
- * to the element object. If several elements named $elementName exist,
- * it removes the first one, leaving the others intact.
- *
- * @param string $elementName The element name
- * @param boolean $removeRules True if rules for this element are to be removed too
- * @access public
- * @since 2.0
- * @return HTML_QuickForm_element a reference to the removed element
- * @throws HTML_QuickForm_Error
- */
- function &removeElement($elementName, $removeRules = true)
- {
- if (!isset($this->_elementIndex[$elementName])) {
- $error = PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$elementName' does not exist in HTML_QuickForm::removeElement()", 'HTML_QuickForm_Error', true);
- return $error;
- }
- $el =& $this->_elements[$this->_elementIndex[$elementName]];
- unset($this->_elements[$this->_elementIndex[$elementName]]);
- if (empty($this->_duplicateIndex[$elementName])) {
- unset($this->_elementIndex[$elementName]);
- } else {
- $this->_elementIndex[$elementName] = array_shift($this->_duplicateIndex[$elementName]);
- }
- if ($removeRules) {
- $this->_required = array_diff($this->_required, array($elementName));
- unset($this->_rules[$elementName], $this->_errors[$elementName]);
- if ('group' == $el->getType()) {
- foreach (array_keys($el->getElements()) as $key) {
- unset($this->_rules[$el->getElementName($key)]);
- }
- }
- }
- return $el;
- } // end func removeElement
-
- // }}}
- // {{{ addRule()
-
- /**
- * Adds a validation rule for the given field
- *
- * If the element is in fact a group, it will be considered as a whole.
- * To validate grouped elements as separated entities,
- * use addGroupRule instead of addRule.
- *
- * @param string $element Form element name
- * @param string $message Message to display for invalid data
- * @param string $type Rule type, use getRegisteredRules() to get types
- * @param string $format (optional)Required for extra rule data
- * @param string $validation (optional)Where to perform validation: "server", "client"
- * @param boolean $reset Client-side validation: reset the form element to its original value if there is an error?
- * @param boolean $force Force the rule to be applied, even if the target form element does not exist
- * @since 1.0
- * @access public
- * @throws HTML_QuickForm_Error
- */
- function addRule($element, $message, $type, $format=null, $validation='server', $reset = false, $force = false)
- {
- if (!$force) {
- if (!is_array($element) && !$this->elementExists($element)) {
- return PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::addRule()", 'HTML_QuickForm_Error', true);
- } elseif (is_array($element)) {
- foreach ($element as $el) {
- if (!$this->elementExists($el)) {
- return PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$el' does not exist in HTML_QuickForm::addRule()", 'HTML_QuickForm_Error', true);
- }
- }
- }
- }
- if (false === ($newName = $this->isRuleRegistered($type, true))) {
- return PEAR::raiseError(null, QUICKFORM_INVALID_RULE, null, E_USER_WARNING, "Rule '$type' is not registered in HTML_QuickForm::addRule()", 'HTML_QuickForm_Error', true);
- } elseif (is_string($newName)) {
- $type = $newName;
- }
- if (is_array($element)) {
- $dependent = $element;
- $element = array_shift($dependent);
- } else {
- $dependent = null;
- }
- if ($type == 'required' || $type == 'uploadedfile') {
- $this->_required[] = $element;
- }
- if (!isset($this->_rules[$element])) {
- $this->_rules[$element] = array();
- }
- if ($validation == 'client') {
- $this->updateAttributes(array('onsubmit' => 'try { var myValidator = validate_' . $this->_attributes['id'] . '; } catch(e) { return true; } return myValidator(this);'));
- }
- $this->_rules[$element][] = array(
- 'type' => $type,
- 'format' => $format,
- 'message' => $message,
- 'validation' => $validation,
- 'reset' => $reset,
- 'dependent' => $dependent
- );
- } // end func addRule
-
- // }}}
- // {{{ addGroupRule()
-
- /**
- * Adds a validation rule for the given group of elements
- *
- * Only groups with a name can be assigned a validation rule
- * Use addGroupRule when you need to validate elements inside the group.
- * Use addRule if you need to validate the group as a whole. In this case,
- * the same rule will be applied to all elements in the group.
- * Use addRule if you need to validate the group against a function.
- *
- * @param string $group Form group name
- * @param mixed $arg1 Array for multiple elements or error message string for one element
- * @param string $type (optional)Rule type use getRegisteredRules() to get types
- * @param string $format (optional)Required for extra rule data
- * @param int $howmany (optional)How many valid elements should be in the group
- * @param string $validation (optional)Where to perform validation: "server", "client"
- * @param bool $reset Client-side: whether to reset the element's value to its original state if validation failed.
- * @since 2.5
- * @access public
- * @throws HTML_QuickForm_Error
- */
- function addGroupRule($group, $arg1, $type='', $format=null, $howmany=0, $validation = 'server', $reset = false)
- {
- if (!$this->elementExists($group)) {
- return PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Group '$group' does not exist in HTML_QuickForm::addGroupRule()", 'HTML_QuickForm_Error', true);
- }
-
- $groupObj =& $this->getElement($group);
- if (is_array($arg1)) {
- $required = 0;
- foreach ($arg1 as $elementIndex => $rules) {
- $elementName = $groupObj->getElementName($elementIndex);
- foreach ($rules as $rule) {
- $format = (isset($rule[2])) ? $rule[2] : null;
- $validation = (isset($rule[3]) && 'client' == $rule[3])? 'client': 'server';
- $reset = isset($rule[4]) && $rule[4];
- $type = $rule[1];
- if (false === ($newName = $this->isRuleRegistered($type, true))) {
- return PEAR::raiseError(null, QUICKFORM_INVALID_RULE, null, E_USER_WARNING, "Rule '$type' is not registered in HTML_QuickForm::addGroupRule()", 'HTML_QuickForm_Error', true);
- } elseif (is_string($newName)) {
- $type = $newName;
- }
-
- $this->_rules[$elementName][] = array(
- 'type' => $type,
- 'format' => $format,
- 'message' => $rule[0],
- 'validation' => $validation,
- 'reset' => $reset,
- 'group' => $group);
-
- if ('required' == $type || 'uploadedfile' == $type) {
- $groupObj->_required[] = $elementName;
- $this->_required[] = $elementName;
- $required++;
- }
- if ('client' == $validation) {
- $this->updateAttributes(array('onsubmit' => 'try { var myValidator = validate_' . $this->_attributes['id'] . '; } catch(e) { return true; } return myValidator(this);'));
- }
- }
- }
- if ($required > 0 && count($groupObj->getElements()) == $required) {
- $this->_required[] = $group;
- }
- } elseif (is_string($arg1)) {
- if (false === ($newName = $this->isRuleRegistered($type, true))) {
- return PEAR::raiseError(null, QUICKFORM_INVALID_RULE, null, E_USER_WARNING, "Rule '$type' is not registered in HTML_QuickForm::addGroupRule()", 'HTML_QuickForm_Error', true);
- } elseif (is_string($newName)) {
- $type = $newName;
- }
-
- // addGroupRule() should also handle <select multiple>
- if (is_a($groupObj, 'html_quickform_group')) {
- // Radios need to be handled differently when required
- if ($type == 'required' && $groupObj->getGroupType() == 'radio') {
- $howmany = ($howmany == 0) ? 1 : $howmany;
- } else {
- $howmany = ($howmany == 0) ? count($groupObj->getElements()) : $howmany;
- }
- }
-
- $this->_rules[$group][] = array('type' => $type,
- 'format' => $format,
- 'message' => $arg1,
- 'validation' => $validation,
- 'howmany' => $howmany,
- 'reset' => $reset);
- if ($type == 'required') {
- $this->_required[] = $group;
- }
- if ($validation == 'client') {
- $this->updateAttributes(array('onsubmit' => 'try { var myValidator = validate_' . $this->_attributes['id'] . '; } catch(e) { return true; } return myValidator(this);'));
- }
- }
- } // end func addGroupRule
-
- // }}}
- // {{{ addFormRule()
-
- /**
- * Adds a global validation rule
- *
- * This should be used when for a rule involving several fields or if
- * you want to use some completely custom validation for your form.
- * The rule function/method should return true in case of successful
- * validation and array('element name' => 'error') when there were errors.
- *
- * @access public
- * @param mixed Callback, either function name or array(&$object, 'method')
- * @throws HTML_QuickForm_Error
- */
- function addFormRule($rule)
- {
- if (!is_callable($rule)) {
- return PEAR::raiseError(null, QUICKFORM_INVALID_RULE, null, E_USER_WARNING, 'Callback function does not exist in HTML_QuickForm::addFormRule()', 'HTML_QuickForm_Error', true);
- }
- $this->_formRules[] = $rule;
- }
-
- // }}}
- // {{{ applyFilter()
-
- /**
- * Applies a data filter for the given field(s)
- *
- * @param mixed $element Form element name or array of such names
- * @param mixed $filter Callback, either function name or array(&$object, 'method')
- * @since 2.0
- * @access public
- * @throws HTML_QuickForm_Error
- */
- function applyFilter($element, $filter)
- {
- if (!is_callable($filter)) {
- return PEAR::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::applyFilter()", 'HTML_QuickForm_Error', true);
- }
- if ($element == '__ALL__') {
- $this->_submitValues = $this->_recursiveFilter($filter, $this->_submitValues);
- } else {
- if (!is_array($element)) {
- $element = array($element);
- }
- foreach ($element as $elName) {
- $value = $this->getSubmitValue($elName);
- if (null !== $value) {
- if (false === strpos($elName, '[')) {
- $this->_submitValues[$elName] = $this->_recursiveFilter($filter, $value);
- } else {
- $idx = "['" . str_replace(
- array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"),
- $elName
- ) . "']";
- eval("\$this->_submitValues{$idx} = \$this->_recursiveFilter(\$filter, \$value);");
- }
- }
- }
- }
- } // end func applyFilter
-
- // }}}
- // {{{ _recursiveFilter()
-
- /**
- * Recursively apply a filter function
- *
- * @param string $filter filter to apply
- * @param mixed $value submitted values
- * @since 2.0
- * @access private
- * @return cleaned values
- */
- function _recursiveFilter($filter, $value)
- {
- if (is_array($value)) {
- $cleanValues = array();
- foreach ($value as $k => $v) {
- $cleanValues[$k] = $this->_recursiveFilter($filter, $v);
- }
- return $cleanValues;
- } else {
- return call_user_func($filter, $value);
- }
- } // end func _recursiveFilter
-
- // }}}
- // {{{ arrayMerge()
-
- /**
- * Merges two arrays
- *
- * Merges two array like the PHP function array_merge but recursively.
- * The main difference is that existing keys will not be renumbered
- * if they are integers.
- *
- * @access public
- * @param array $a original array
- * @param array $b array which will be merged into first one
- * @return array merged array
- */
- function arrayMerge($a, $b)
- {
- foreach ($b as $k => $v) {
- if (is_array($v)) {
- if (isset($a[$k]) && !is_array($a[$k])) {
- $a[$k] = $v;
- } else {
- if (!isset($a[$k])) {
- $a[$k] = array();
- }
- $a[$k] = HTML_QuickForm::arrayMerge($a[$k], $v);
- }
- } else {
- $a[$k] = $v;
- }
- }
- return $a;
- } // end func arrayMerge
-
- // }}}
- // {{{ isTypeRegistered()
-
- /**
- * Returns whether or not the form element type is supported
- *
- * @param string $type Form element type
- * @since 1.0
- * @access public
- * @return boolean
- */
- function isTypeRegistered($type)
- {
- return isset($GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][strtolower($type)]);
- } // end func isTypeRegistered
-
- // }}}
- // {{{ getRegisteredTypes()
-
- /**
- * Returns an array of registered element types
- *
- * @since 1.0
- * @access public
- * @return array
- */
- function getRegisteredTypes()
- {
- return array_keys($GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES']);
- } // end func getRegisteredTypes
-
- // }}}
- // {{{ isRuleRegistered()
-
- /**
- * Returns whether or not the given rule is supported
- *
- * @param string $name Validation rule name
- * @param bool Whether to automatically register subclasses of HTML_QuickForm_Rule
- * @since 1.0
- * @access public
- * @return mixed true if previously registered, false if not, new rule name if auto-registering worked
- */
- function isRuleRegistered($name, $autoRegister = false)
- {
- if (is_scalar($name) && isset($GLOBALS['_HTML_QuickForm_registered_rules'][$name])) {
- return true;
- } elseif (!$autoRegister) {
- return false;
- }
- // automatically register the rule if requested
- include_once 'HTML/QuickForm/RuleRegistry.php';
- $ruleName = false;
- if (is_object($name) && is_a($name, 'html_quickform_rule')) {
- $ruleName = !empty($name->name)? $name->name: strtolower(get_class($name));
- } elseif (is_string($name) && class_exists($name)) {
- $parent = strtolower($name);
- do {
- if ('html_quickform_rule' == strtolower($parent)) {
- $ruleName = strtolower($name);
- break;
- }
- } while ($parent = get_parent_class($parent));
- }
- if ($ruleName) {
- $registry =& HTML_QuickForm_RuleRegistry::singleton();
- $registry->registerRule($ruleName, null, $name);
- }
- return $ruleName;
- } // end func isRuleRegistered
-
- // }}}
- // {{{ getRegisteredRules()
-
- /**
- * Returns an array of registered validation rules
- *
- * @since 1.0
- * @access public
- * @return array
- */
- function getRegisteredRules()
- {
- return array_keys($GLOBALS['_HTML_QuickForm_registered_rules']);
- } // end func getRegisteredRules
-
- // }}}
- // {{{ isElementRequired()
-
- /**
- * Returns whether or not the form element is required
- *
- * @param string $element Form element name
- * @since 1.0
- * @access public
- * @return boolean
- */
- function isElementRequired($element)
- {
- return in_array($element, $this->_required, true);
- } // end func isElementRequired
-
- // }}}
- // {{{ isElementFrozen()
-
- /**
- * Returns whether or not the form element is frozen
- *
- * @param string $element Form element name
- * @since 1.0
- * @access public
- * @return boolean
- */
- function isElementFrozen($element)
- {
- if (isset($this->_elementIndex[$element])) {
- return $this->_elements[$this->_elementIndex[$element]]->isFrozen();
- }
- return false;
- } // end func isElementFrozen
-
- // }}}
- // {{{ setJsWarnings()
-
- /**
- * Sets JavaScript warning messages
- *
- * @param string $pref Prefix warning
- * @param string $post Postfix warning
- * @since 1.1
- * @access public
- * @return void
- */
- function setJsWarnings($pref, $post)
- {
- $this->_jsPrefix = $pref;
- $this->_jsPostfix = $post;
- } // end func setJsWarnings
-
- // }}}
- // {{{ setRequiredNote()
-
- /**
- * Sets required-note
- *
- * @param string $note Message indicating some elements are required
- * @since 1.1
- * @access public
- * @return void
- */
- function setRequiredNote($note)
- {
- $this->_requiredNote = $note;
- } // end func setRequiredNote
-
- // }}}
- // {{{ getRequiredNote()
-
- /**
- * Returns the required note
- *
- * @since 2.0
- * @access public
- * @return string
- */
- function getRequiredNote()
- {
- return $this->_requiredNote;
- } // end func getRequiredNote
-
- // }}}
- // {{{ validate()
-
- /**
- * Performs the server side validation
- * @access public
- * @since 1.0
- * @return boolean true if no error found
- * @throws HTML_QuickForm_Error
- */
- function validate()
- {
- if (count($this->_rules) == 0 && count($this->_formRules) == 0 &&
- $this->isSubmitted()) {
- return (0 == count($this->_errors));
- } elseif (!$this->isSubmitted()) {
- return false;
- }
-
- include_once('HTML/QuickForm/RuleRegistry.php');
- $registry =& HTML_QuickForm_RuleRegistry::singleton();
-
- foreach ($this->_rules as $target => $rules) {
- $submitValue = $this->getSubmitValue($target);
-
- foreach ($rules as $rule) {
- if ((isset($rule['group']) && isset($this->_errors[$rule['group']])) ||
- isset($this->_errors[$target])) {
- continue 2;
- }
- // If element is not required and is empty, we shouldn't validate it
- if (!$this->isElementRequired($target)) {
- if (!isset($submitValue) || '' == $submitValue) {
- continue 2;
- // Fix for bug #3501: we shouldn't validate not uploaded files, either.
- // Unfortunately, we can't just use $element->isUploadedFile() since
- // the element in question can be buried in group. Thus this hack.
- // See also bug #12014, we should only consider a file that has
- // status UPLOAD_ERR_NO_FILE as not uploaded, in all other cases
- // validation should be performed, so that e.g. 'maxfilesize' rule
- // will display an error if status is UPLOAD_ERR_INI_SIZE
- // or UPLOAD_ERR_FORM_SIZE
- } elseif (is_array($submitValue)) {
- if (false === ($pos = strpos($target, '['))) {
- $isUpload = !empty($this->_submitFiles[$target]);
- } else {
- $base = str_replace(
- array('\\', '\''), array('\\\\', '\\\''),
- substr($target, 0, $pos)
- );
- $idx = "['" . str_replace(
- array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"),
- substr($target, $pos + 1, -1)
- ) . "']";
- eval("\$isUpload = isset(\$this->_submitFiles['{$base}']['name']{$idx});");
- }
- if ($isUpload && (!isset($submitValue['error']) || UPLOAD_ERR_NO_FILE == $submitValue['error'])) {
- continue 2;
- }
- }
- }
- if (isset($rule['dependent']) && is_array($rule['dependent'])) {
- $values = array($submitValue);
- foreach ($rule['dependent'] as $elName) {
- $values[] = $this->getSubmitValue($elName);
- }
- $result = $registry->validate($rule['type'], $values, $rule['format'], true);
- } elseif (is_array($submitValue) && !isset($rule['howmany'])) {
- $result = $registry->validate($rule['type'], $submitValue, $rule['format'], true);
- } else {
- $result = $registry->validate($rule['type'], $submitValue, $rule['format'], false);
- }
-
- if (!$result || (!empty($rule['howmany']) && $rule['howmany'] > (int)$result)) {
- if (isset($rule['group'])) {
- $this->_errors[$rule['group']] = $rule['message'];
- } else {
- $this->_errors[$target] = $rule['message'];
- }
- }
- }
- }
-
- // process the global rules now
- foreach ($this->_formRules as $rule) {
- if (true !== ($res = call_user_func($rule, $this->_submitValues, $this->_submitFiles))) {
- if (is_array($res)) {
- $this->_errors += $res;
- } else {
- return PEAR::raiseError(null, QUICKFORM_ERROR, null, E_USER_WARNING, 'Form rule callback returned invalid value in HTML_QuickForm::validate()', 'HTML_QuickForm_Error', true);
- }
- }
- }
-
- return (0 == count($this->_errors));
- } // end func validate
-
- // }}}
- // {{{ freeze()
-
- /**
- * Displays elements without HTML input tags
- *
- * @param mixed $elementList array or string of element(s) to be frozen
- * @since 1.0
- * @access public
- * @throws HTML_QuickForm_Error
- */
- function freeze($elementList=null)
- {
- if (!isset($elementList)) {
- $this->_freezeAll = true;
- $elementList = array();
- } else {
- if (!is_array($elementList)) {
- $elementList = preg_split('/[ ]*,[ ]*/', $elementList);
- }
- $elementList = array_flip($elementList);
- }
-
- foreach (array_keys($this->_elements) as $key) {
- $name = $this->_elements[$key]->getName();
- if ($this->_freezeAll || isset($elementList[$name])) {
- $this->_elements[$key]->freeze();
- unset($elementList[$name]);
- }
- }
-
- if (!empty($elementList)) {
- return PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Nonexistant element(s): '" . implode("', '", array_keys($elementList)) . "' in HTML_QuickForm::freeze()", 'HTML_QuickForm_Error', true);
- }
- return true;
- } // end func freeze
-
- // }}}
- // {{{ isFrozen()
-
- /**
- * Returns whether or not the whole form is frozen
- *
- * @since 3.0
- * @access public
- * @return boolean
- */
- function isFrozen()
- {
- return $this->_freezeAll;
- } // end func isFrozen
-
- // }}}
- // {{{ process()
-
- /**
- * Performs the form data processing
- *
- * @param mixed $callback Callback, either function name or array(&$object, 'method')
- * @param bool $mergeFiles Whether uploaded files should be processed too
- * @since 1.0
- * @access public
- * @throws HTML_QuickForm_Error
- * @return mixed Whatever value the $callback function returns
- */
- function process($callback, $mergeFiles = true)
- {
- if (!is_callable($callback)) {
- return PEAR::raiseError(null, QUICKFORM_INVALID_PROCESS, null, E_USER_WARNING, "Callback function does not exist in QuickForm::process()", 'HTML_QuickForm_Error', true);
- }
- $values = ($mergeFiles === true) ? HTML_QuickForm::arrayMerge($this->_submitValues, $this->_submitFiles) : $this->_submitValues;
- return call_user_func($callback, $values);
- } // end func process
-
- // }}}
- // {{{ accept()
-
- /**
- * Accepts a renderer
- *
- * @param object An HTML_QuickForm_Renderer object
- * @since 3.0
- * @access public
- * @return void
- */
- function accept(&$renderer)
- {
- $renderer->startForm($this);
- foreach (array_keys($this->_elements) as $key) {
- $element =& $this->_elements[$key];
- $elementName = $element->getName();
- $required = ($this->isElementRequired($elementName) && !$element->isFrozen());
- $error = $this->getElementError($elementName);
- $element->accept($renderer, $required, $error);
- }
- $renderer->finishForm($this);
- } // end func accept
-
- // }}}
- // {{{ defaultRenderer()
-
- /**
- * Returns a reference to default renderer object
- *
- * @access public
- * @since 3.0
- * @return object a default renderer object
- */
- function &defaultRenderer()
- {
- if (!isset($GLOBALS['_HTML_QuickForm_default_renderer'])) {
- include_once('HTML/QuickForm/Renderer/Default.php');
- $GLOBALS['_HTML_QuickForm_default_renderer'] = new HTML_QuickForm_Renderer_Default();
- }
- return $GLOBALS['_HTML_QuickForm_default_renderer'];
- } // end func defaultRenderer
-
- // }}}
- // {{{ toHtml ()
-
- /**
- * Returns an HTML version of the form
- *
- * @param string $in_data (optional) Any extra data to insert right
- * before form is rendered. Useful when using templates.
- *
- * @return string Html version of the form
- * @since 1.0
- * @access public
- */
- function toHtml ($in_data = null)
- {
- if (!is_null($in_data)) {
- $this->addElement('html', $in_data);
- }
- $renderer =& $this->defaultRenderer();
- $this->accept($renderer);
- return $renderer->toHtml();
- } // end func toHtml
-
- // }}}
- // {{{ getValidationScript()
-
- /**
- * Returns the client side validation script
- *
- * @since 2.0
- * @access public
- * @return string Javascript to perform validation, empty string if no 'client' rules were added
- */
- function getValidationScript()
- {
- if (empty($this->_rules) || empty($this->_attributes['onsubmit'])) {
- return '';
- }
-
- include_once('HTML/QuickForm/RuleRegistry.php');
- $registry =& HTML_QuickForm_RuleRegistry::singleton();
- $test = array();
- $js_escape = array(
- "\r" => '\r',
- "\n" => '\n',
- "\t" => '\t',
- "'" => "\\'",
- '"' => '\"',
- '\\' => '\\\\'
- );
-
- foreach ($this->_rules as $elementName => $rules) {
- foreach ($rules as $rule) {
- if ('client' == $rule['validation']) {
- unset($element);
-
- $dependent = isset($rule['dependent']) && is_array($rule['dependent']);
- $rule['message'] = strtr($rule['message'], $js_escape);
-
- if (isset($rule['group'])) {
- $group =& $this->getElement($rule['group']);
- // No JavaScript validation for frozen elements
- if ($group->isFrozen()) {
- continue 2;
- }
- $elements =& $group->getElements();
- foreach (array_keys($elements) as $key) {
- if ($elementName == $group->getElementName($key)) {
- $element =& $elements[$key];
- break;
- }
- }
- } elseif ($dependent) {
- $element = array();
- $element[] =& $this->getElement($elementName);
- foreach ($rule['dependent'] as $elName) {
- $element[] =& $this->getElement($elName);
- }
- } else {
- $element =& $this->getElement($elementName);
- }
- // No JavaScript validation for frozen elements
- if (is_object($element) && $element->isFrozen()) {
- continue 2;
- } elseif (is_array($element)) {
- foreach (array_keys($element) as $key) {
- if ($element[$key]->isFrozen()) {
- continue 3;
- }
- }
- }
-
- $test[] = $registry->getValidationScript($element, $elementName, $rule);
- }
- }
- }
- if (count($test) > 0) {
- return
- "\n<script type=\"text/javascript\">\n" .
- "//<![CDATA[\n" .
- "function validate_" . $this->_attributes['id'] . "(frm) {\n" .
- " var value = '';\n" .
- " var errFlag = new Array();\n" .
- " var _qfGroups = {};\n" .
- " _qfMsg = '';\n\n" .
- join("\n", $test) .
- "\n if (_qfMsg != '') {\n" .
- " _qfMsg = '" . strtr($this->_jsPrefix, $js_escape) . "' + _qfMsg;\n" .
- " _qfMsg = _qfMsg + '\\n" . strtr($this->_jsPostfix, $js_escape) . "';\n" .
- " alert(_qfMsg);\n" .
- " return false;\n" .
- " }\n" .
- " return true;\n" .
- "}\n" .
- "//]]>\n" .
- "</script>";
- }
- return '';
- } // end func getValidationScript
-
- // }}}
- // {{{ getSubmitValues()
-
- /**
- * Returns the values submitted by the form
- *
- * @since 2.0
- * @access public
- * @param bool Whether uploaded files should be returned too
- * @return array
- */
- function getSubmitValues($mergeFiles = false)
- {
- return $mergeFiles? HTML_QuickForm::arrayMerge($this->_submitValues, $this->_submitFiles): $this->_submitValues;
- } // end func getSubmitValues
-
- // }}}
- // {{{ toArray()
-
- /**
- * Returns the form's contents in an array.
- *
- * The description of the array structure is in HTML_QuickForm_Renderer_Array docs
- *
- * @since 2.0
- * @access public
- * @param bool Whether to collect hidden elements (passed to the Renderer's constructor)
- * @return array of form contents
- */
- function toArray($collectHidden = false)
- {
- include_once 'HTML/QuickForm/Renderer/Array.php';
- $renderer = new HTML_QuickForm_Renderer_Array($collectHidden);
- $this->accept($renderer);
- return $renderer->toArray();
- } // end func toArray
-
- // }}}
- // {{{ exportValue()
-
- /**
- * Returns a 'safe' element's value
- *
- * This method first tries to find a cleaned-up submitted value,
- * it will return a value set by setValue()/setDefaults()/setConstants()
- * if submitted value does not exist for the given element.
- *
- * @param string Name of an element
- * @access public
- * @return mixed
- * @throws HTML_QuickForm_Error
- */
- function exportValue($element)
- {
- if (!isset($this->_elementIndex[$element])) {
- return PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::getElementValue()", 'HTML_QuickForm_Error', true);
- }
- $value = $this->_elements[$this->_elementIndex[$element]]->exportValue($this->_submitValues, false);
- if (isset($this->_duplicateIndex[$element])) {
- foreach ($this->_duplicateIndex[$element] as $index) {
- if (null !== ($v = $this->_elements[$index]->exportValue($this->_submitValues, false))) {
- if (is_array($value)) {
- $value[] = $v;
- } else {
- $value = (null === $value)? $v: array($value, $v);
- }
- }
- }
- }
- return $value;
- }
-
- // }}}
- // {{{ exportValues()
-
- /**
- * Returns 'safe' elements' values
- *
- * Unlike getSubmitValues(), this will return only the values
- * corresponding to the elements present in the form.
- *
- * @param mixed Array/string of element names, whose values we want. If not set then return all elements.
- * @access public
- * @return array An assoc array of elements' values
- * @throws HTML_QuickForm_Error
- */
- function exportValues($elementList = null)
- {
- $values = array();
- if (null === $elementList) {
- // iterate over all elements, calling their exportValue() methods
- foreach (array_keys($this->_elements) as $key) {
- $value = $this->_elements[$key]->exportValue($this->_submitValues, true);
- if (is_array($value)) {
- // This shit throws a bogus warning in PHP 4.3.x
- $values = HTML_QuickForm::arrayMerge($values, $value);
- }
- }
- } else {
- if (!is_array($elementList)) {
- $elementList = array_map('trim', explode(',', $elementList));
- }
- foreach ($elementList as $elementName) {
- $value = $this->exportValue($elementName);
- if (PEAR::isError($value)) {
- return $value;
- }
- $values[$elementName] = $value;
- }
- }
- return $values;
- }
-
- // }}}
- // {{{ isSubmitted()
-
- /**
- * Tells whether the form was already submitted
- *
- * This is useful since the _submitFiles and _submitValues arrays
- * may be completely empty after the trackSubmit value is removed.
- *
- * @access public
- * @return bool
- */
- function isSubmitted()
- {
- return $this->_flagSubmitted;
- }
-
-
- // }}}
- // {{{ isError()
-
- /**
- * Tell whether a result from a QuickForm method is an error (an instance of HTML_QuickForm_Error)
- *
- * @access public
- * @param mixed result code
- * @return bool whether $value is an error
- * @static
- */
- function isError($value)
- {
- return (is_object($value) && is_a($value, 'html_quickform_error'));
- } // end func isError
-
- // }}}
- // {{{ errorMessage()
-
- /**
- * Return a textual error message for an QuickForm error code
- *
- * @access public
- * @param int error code
- * @return string error message
- * @static
- */
- function errorMessage($value)
- {
- // make the variable static so that it only has to do the defining on the first call
- static $errorMessages;
-
- // define the varies error messages
- if (!isset($errorMessages)) {
- $errorMessages = array(
- QUICKFORM_OK => 'no error',
- QUICKFORM_ERROR => 'unknown error',
- QUICKFORM_INVALID_RULE => 'the rule does not exist as a registered rule',
- QUICKFORM_NONEXIST_ELEMENT => 'nonexistent html element',
- QUICKFORM_INVALID_FILTER => 'invalid filter',
- QUICKFORM_UNREGISTERED_ELEMENT => 'unregistered element',
- QUICKFORM_INVALID_ELEMENT_NAME => 'element already exists',
- QUICKFORM_INVALID_PROCESS => 'process callback does not exist',
- QUICKFORM_DEPRECATED => 'method is deprecated',
- QUICKFORM_INVALID_DATASOURCE => 'datasource is not an object'
- );
- }
-
- // If this is an error object, then grab the corresponding error code
- if (HTML_QuickForm::isError($value)) {
- $value = $value->getCode();
- }
-
- // return the textual error message corresponding to the code
- return isset($errorMessages[$value]) ? $errorMessages[$value] : $errorMessages[QUICKFORM_ERROR];
- } // end func errorMessage
-
- // }}}
-} // end class HTML_QuickForm
-
-/**
- * Class for errors thrown by HTML_QuickForm package
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @version Release: 3.2.16
- */
-class HTML_QuickForm_Error extends PEAR_Error {
-
- // {{{ properties
-
- /**
- * Prefix for all error messages
- * @var string
- */
- var $error_message_prefix = 'QuickForm Error: ';
-
- // }}}
- // {{{ constructor
-
- /**
- * Creates a quickform error object, extending the PEAR_Error class
- *
- * @param int $code the error code
- * @param int $mode the reaction to the error, either return, die or trigger/callback
- * @param int $level intensity of the error (PHP error code)
- * @param mixed $debuginfo any information that can inform user as to nature of the error
- */
- function HTML_QuickForm_Error($code = QUICKFORM_ERROR, $mode = PEAR_ERROR_RETURN,
- $level = E_USER_NOTICE, $debuginfo = null)
- {
- if (is_int($code)) {
- $this->PEAR_Error(HTML_QuickForm::errorMessage($code), $code, $mode, $level, $debuginfo);
- } else {
- $this->PEAR_Error("Invalid error code: $code", QUICKFORM_ERROR, $mode, $level, $debuginfo);
- }
- }
-
- // }}}
-} // end class HTML_QuickForm_Error
-?>
+++ /dev/null
-<?php
-/**
- * DHTML replacement for the standard JavaScript alert window for client-side
- * validation
- *
- * LICENSE:
- *
- * Copyright (c) 2005-2007, Mark Wiesemann <wiesemann@php.net>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * The names of the authors may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * @category HTML
- * @package HTML_QuickForm_DHTMLRulesTableless
- * @author Alexey Borzov <borz_off@cs.msu.su>
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Justin Patrin <papercrane@gmail.com>
- * @author Mark Wiesemann <wiesemann@php.net>
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: DHTMLRulesTableless.php,v 1.10 2007/10/24 20:36:11 wiesemann Exp $
- * @link http://pear.php.net/package/HTML_QuickForm_DHTMLRulesTableless
- */
-
-require_once 'HTML/QuickForm.php';
-
-/**
- * This is a DHTML replacement for the standard JavaScript alert window for
- * client-side validation of forms built with HTML_QuickForm
- *
- * @category HTML
- * @package HTML_QuickForm_DHTMLRulesTableless
- * @author Alexey Borzov <borz_off@cs.msu.su>
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Justin Patrin <papercrane@gmail.com>
- * @author Mark Wiesemann <wiesemann@php.net>
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 0.3.3
- * @link http://pear.php.net/package/HTML_QuickForm_DHTMLRulesTableless
- */
-class HTML_QuickForm_DHTMLRulesTableless extends HTML_QuickForm {
- // {{{ getValidationScript()
-
- /**
- * Returns the client side validation script
- *
- * The code here was copied from HTML_QuickForm and slightly modified to run rules per-element
- *
- * @access public
- * @return string Javascript to perform validation, empty string if no 'client' rules were added
- */
- function getValidationScript()
- {
- if (empty($this->_rules) || empty($this->_attributes['onsubmit'])) {
- return '';
- }
-
- include_once('HTML/QuickForm/RuleRegistry.php');
- $registry =& HTML_QuickForm_RuleRegistry::singleton();
- $test = array();
- $js_escape = array(
- "\r" => '\r',
- "\n" => '\n',
- "\t" => '\t',
- "'" => "\\'",
- '"' => '\"',
- '\\' => '\\\\'
- );
-
- foreach ($this->_rules as $elementName => $rules) {
- foreach ($rules as $rule) {
- if ('client' == $rule['validation']) {
- unset($element);
-
- $dependent = isset($rule['dependent']) && is_array($rule['dependent']);
- $rule['message'] = strtr($rule['message'], $js_escape);
-
- if (isset($rule['group'])) {
- $group =& $this->getElement($rule['group']);
- // No JavaScript validation for frozen elements
- if ($group->isFrozen()) {
- continue 2;
- }
- $elements =& $group->getElements();
- foreach (array_keys($elements) as $key) {
- if ($elementName == $group->getElementName($key)) {
- $element =& $elements[$key];
- break;
- }
- }
- } elseif ($dependent) {
- $element = array();
- $element[] =& $this->getElement($elementName);
- foreach ($rule['dependent'] as $idx => $elName) {
- $element[] =& $this->getElement($elName);
- }
- } else {
- $element =& $this->getElement($elementName);
- }
- // No JavaScript validation for frozen elements
- if (is_object($element) && $element->isFrozen()) {
- continue 2;
- } elseif (is_array($element)) {
- foreach (array_keys($element) as $key) {
- if ($element[$key]->isFrozen()) {
- continue 3;
- }
- }
- }
-
- $test[$elementName][] = $registry->getValidationScript($element, $elementName, $rule);
- }
- }
- }
- $js = '
-<script type="text/javascript"><!--//--><![CDATA[//><!--
-qf_errorHandler = function(element, _qfMsg) {
- div = element.parentNode;
- var elementName = element.name.replace(/\[/, "_____");
- var elementName = elementName.replace(/\]/, "_____");
- if (_qfMsg != \'\') {
- span = document.createElement("span");
- span.className = "error";
- _qfMsg = _qfMsg.substring(4);
- span.appendChild(document.createTextNode(_qfMsg));
- br = document.createElement("br");
-
- var errorDiv = document.getElementById(elementName + \'_errorDiv\');
- if (!errorDiv) {
- errorDiv = document.createElement("div");
- errorDiv.id = elementName + \'_errorDiv\';
- } else {
- if ( div.firstChild.textContent == \'\'
- || _qfMsg == div.firstChild.textContent
- ) {
- return false;
- }
- }
- while (errorDiv.firstChild) {
- errorDiv.removeChild(errorDiv.firstChild);
- }
-
- errorDiv.insertBefore(br, errorDiv.firstChild);
- errorDiv.insertBefore(span, errorDiv.firstChild);
-
- errorDivInserted = false;
- for (var i = element.parentNode.childNodes.length - 1; i >= 0; i--) {
- j = i - 1;
- if (j >= 0 && element.parentNode.childNodes[j].nodeName == "DIV") {
- element.parentNode.insertBefore(errorDiv, element.parentNode.childNodes[i]);
- errorDivInserted = true;
- break;
- }
- }
- if (!errorDivInserted) {
- element.parentNode.insertBefore(errorDiv, element.parentNode.firstChild);
- }
-
- if (div.className.substr(div.className.length - 6, 6) != " error"
- && div.className != "error") {
- div.className += " error";
- }
-
- return false;
- } else {
- var errorDiv = document.getElementById(elementName + \'_errorDiv\');
- if (errorDiv) {
- errorDiv.parentNode.removeChild(errorDiv);
- }
-
- // do not remove the error style from the div tag if there is still an error
- // message
- if (div.firstChild.innerHTML != "") {
- return true;
- }
-
- if (div.className.substr(div.className.length - 6, 6) == " error") {
- div.className = div.className.substr(0, div.className.length - 6);
- } else if (div.className == "error") {
- div.className = "";
- }
-
- return true;
- }
-}';
- $validateJS = '';
- foreach ($test as $elementName => $jsArr) {
- // remove group element part of the element name to avoid JS errors
- $singleElementName = $elementName;
- $shortNameForJS = str_replace(array('[', ']'), '__', $elementName);
- $bracketPos = strpos($elementName, '[');
- if ($bracketPos !== false) {
- $singleElementName = substr($elementName, 0, $bracketPos);
- $groupElementName = substr($elementName, $bracketPos + 1, -1);
- }
- if ($bracketPos === false || !$this->elementExists($singleElementName)) {
- $groupElementName = $elementName;
- $singleElementName = $elementName;
- }
- $id = str_replace('-', '_', $this->_attributes['id']);
- $js .= '
-validate_' . $id . '_' . $shortNameForJS . ' = function(element) {
- var value = \'\';
- var errFlag = new Array();
- var _qfGroups = {};
- var _qfMsg = \'\';
- var frm = element.parentNode;
- while (frm && frm.nodeName != "FORM") {
- frm = frm.parentNode;
- }
-' . join("\n", $jsArr) . '
- return qf_errorHandler(element, _qfMsg);
-}
-';
- unset($element);
- $element =& $this->getElement($singleElementName);
- $elementNameForJS = 'frm.elements[\'' . $elementName . '\']';
- if ($element->getType() === 'group' && $singleElementName === $elementName) {
- $elementNameForJS = 'document.getElementById(\'' . $element->_elements[0]->getAttribute('id') . '\')';
- }
- $validateJS .= '
- ret = validate_' . $id . '_' . $shortNameForJS . '('. $elementNameForJS . ') && ret;';
- if ($element->getType() !== 'group') { // not a group
- $valFunc = 'validate_' . $id . '_' . $shortNameForJS . '(this)';
- $onBlur = $element->getAttribute('onBlur');
- $onChange = $element->getAttribute('onChange');
- $element->updateAttributes(array('onBlur' => $onBlur . $valFunc,
- 'onChange' => $onChange . $valFunc));
- } else { // group
- $elements =& $element->getElements();
- for ($i = 0; $i < count($elements); $i++) {
- // $groupElementName is a substring of attribute name of the element
- if (strpos($elements[$i]->getAttribute('name'), $groupElementName) === 0) {
- $valFunc = 'validate_' . $id . '_' . $shortNameForJS . '(this)';
- $onBlur = $elements[$i]->getAttribute('onBlur');
- $onChange = $elements[$i]->getAttribute('onChange');
- $elements[$i]->updateAttributes(array('onBlur' => $onBlur . $valFunc,
- 'onChange' => $onChange . $valFunc));
- }
- }
- }
- }
- $js .= '
-validate_' . $id . ' = function(frm) {
- var ret = true;
-' . $validateJS . ';
- return ret;
-}
-//--><!]]></script>';
- return $js;
- } // end func getValidationScript
-
- // }}}
-
- function display() {
- $this->getValidationScript();
- return parent::display();
- }
-}
-
-?>
\ No newline at end of file
+++ /dev/null
-<?php
-/**
- * DHTML replacement for the standard JavaScript alert window for client-side
- * validation
- *
- * LICENSE:
- *
- * Copyright (c) 2005-2007, Mark Wiesemann <wiesemann@php.net>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * The names of the authors may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * @category HTML
- * @package HTML_QuickForm_DHTMLRulesTableless
- * @author Alexey Borzov <borz_off@cs.msu.su>
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Justin Patrin <papercrane@gmail.com>
- * @author Mark Wiesemann <wiesemann@php.net>
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: PageDHTMLRulesTableless.php,v 1.3 2007/10/24 20:36:11 wiesemann Exp $
- * @link http://pear.php.net/package/HTML_QuickForm_DHTMLRulesTableless
- */
-
-require_once 'HTML/QuickForm/Page.php';
-
-/**
- * This is a DHTML replacement for the standard JavaScript alert window for
- * client-side validation of forms built with HTML_QuickForm
- *
- * @category HTML
- * @package HTML_QuickForm_DHTMLRulesTableless
- * @author Alexey Borzov <borz_off@cs.msu.su>
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Justin Patrin <papercrane@gmail.com>
- * @author Mark Wiesemann <wiesemann@php.net>
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 0.3.3
- * @link http://pear.php.net/package/HTML_QuickForm_DHTMLRulesTableless
- */
-class HTML_QuickForm_PageDHTMLRulesTableless extends HTML_QuickForm_Page
-{
- /**
- * Class constructor
- *
- * @access public
- */
- function HTML_QuickForm_PageDHTMLRulesTableless($formName, $method = 'post',
- $target = '', $attributes = null)
- {
- $this->HTML_QuickForm_Page($formName, $method, '', $target, $attributes);
- }
-
- // {{{ getValidationScript()
-
- /**
- * Returns the client side validation script
- *
- * The code here was copied from HTML_QuickForm and slightly modified to run rules per-element
- *
- * @access public
- * @return string Javascript to perform validation, empty string if no 'client' rules were added
- */
- function getValidationScript()
- {
- if (empty($this->_rules) || empty($this->_attributes['onsubmit'])) {
- return '';
- }
-
- include_once('HTML/QuickForm/RuleRegistry.php');
- $registry =& HTML_QuickForm_RuleRegistry::singleton();
- $test = array();
- $js_escape = array(
- "\r" => '\r',
- "\n" => '\n',
- "\t" => '\t',
- "'" => "\\'",
- '"' => '\"',
- '\\' => '\\\\'
- );
-
- foreach ($this->_rules as $elementName => $rules) {
- foreach ($rules as $rule) {
- if ('client' == $rule['validation']) {
- unset($element);
-
- $dependent = isset($rule['dependent']) && is_array($rule['dependent']);
- $rule['message'] = strtr($rule['message'], $js_escape);
-
- if (isset($rule['group'])) {
- $group =& $this->getElement($rule['group']);
- // No JavaScript validation for frozen elements
- if ($group->isFrozen()) {
- continue 2;
- }
- $elements =& $group->getElements();
- foreach (array_keys($elements) as $key) {
- if ($elementName == $group->getElementName($key)) {
- $element =& $elements[$key];
- break;
- }
- }
- } elseif ($dependent) {
- $element = array();
- $element[] =& $this->getElement($elementName);
- foreach ($rule['dependent'] as $idx => $elName) {
- $element[] =& $this->getElement($elName);
- }
- } else {
- $element =& $this->getElement($elementName);
- }
- // No JavaScript validation for frozen elements
- if (is_object($element) && $element->isFrozen()) {
- continue 2;
- } elseif (is_array($element)) {
- foreach (array_keys($element) as $key) {
- if ($element[$key]->isFrozen()) {
- continue 3;
- }
- }
- }
-
- $test[$elementName][] = $registry->getValidationScript($element, $elementName, $rule);
- }
- }
- }
- $js = '
-<script type="text/javascript"><!--//--><![CDATA[//><!--
-qf_errorHandler = function(element, _qfMsg) {
- div = element.parentNode;
- var elementName = element.name.replace(/\[/, "_____");
- var elementName = elementName.replace(/\]/, "_____");
- if (_qfMsg != \'\') {
- span = document.createElement("span");
- span.className = "error";
- _qfMsg = _qfMsg.substring(4);
- span.appendChild(document.createTextNode(_qfMsg));
- br = document.createElement("br");
-
- var errorDiv = document.getElementById(elementName + \'_errorDiv\');
- if (!errorDiv) {
- errorDiv = document.createElement("div");
- errorDiv.id = elementName + \'_errorDiv\';
- } else {
- if ( div.firstChild.textContent == \'\'
- || _qfMsg == div.firstChild.textContent
- ) {
- return false;
- }
- }
- while (errorDiv.firstChild) {
- errorDiv.removeChild(errorDiv.firstChild);
- }
-
- errorDiv.insertBefore(br, errorDiv.firstChild);
- errorDiv.insertBefore(span, errorDiv.firstChild);
-
- errorDivInserted = false;
- for (var i = element.parentNode.childNodes.length - 1; i >= 0; i--) {
- j = i - 1;
- if (j >= 0 && element.parentNode.childNodes[j].nodeName == "DIV") {
- element.parentNode.insertBefore(errorDiv, element.parentNode.childNodes[i]);
- errorDivInserted = true;
- break;
- }
- }
- if (!errorDivInserted) {
- element.parentNode.insertBefore(errorDiv, element.parentNode.firstChild);
- }
-
- if (div.className.substr(div.className.length - 6, 6) != " error"
- && div.className != "error") {
- div.className += " error";
- }
-
- return false;
- } else {
- var errorDiv = document.getElementById(elementName + \'_errorDiv\');
- if (errorDiv) {
- errorDiv.parentNode.removeChild(errorDiv);
- }
-
- // do not remove the error style from the div tag if there is still an error
- // message
- if (div.firstChild.innerHTML != "") {
- return true;
- }
-
- if (div.className.substr(div.className.length - 6, 6) == " error") {
- div.className = div.className.substr(0, div.className.length - 6);
- } else if (div.className == "error") {
- div.className = "";
- }
-
- return true;
- }
-}';
- $validateJS = '';
- foreach ($test as $elementName => $jsArr) {
- // remove group element part of the element name to avoid JS errors
- $singleElementName = $elementName;
- $shortNameForJS = str_replace(array('[', ']'), '__', $elementName);
- $bracketPos = strpos($elementName, '[');
- if ($bracketPos !== false) {
- $singleElementName = substr($elementName, 0, $bracketPos);
- $groupElementName = substr($elementName, $bracketPos + 1, -1);
- }
- if ($bracketPos === false || !$this->elementExists($singleElementName)) {
- $groupElementName = $elementName;
- $singleElementName = $elementName;
- }
- $id = str_replace('-', '_', $this->_attributes['id']);
- $js .= '
-validate_' . $id . '_' . $shortNameForJS . ' = function(element) {
- var value = \'\';
- var errFlag = new Array();
- var _qfGroups = {};
- var _qfMsg = \'\';
- var frm = element.parentNode;
- while (frm && frm.nodeName != "FORM") {
- frm = frm.parentNode;
- }
-' . join("\n", $jsArr) . '
- return qf_errorHandler(element, _qfMsg);
-}
-';
- unset($element);
- $element =& $this->getElement($singleElementName);
- $elementNameForJS = 'frm.elements[\'' . $elementName . '\']';
- if ($element->getType() === 'group' && $singleElementName === $elementName) {
- $elementNameForJS = 'document.getElementById(\'' . $element->_elements[0]->getAttribute('id') . '\')';
- }
- $validateJS .= '
- ret = validate_' . $id . '_' . $shortNameForJS . '('. $elementNameForJS . ') && ret;';
- if ($element->getType() !== 'group') { // not a group
- $valFunc = 'validate_' . $id . '_' . $shortNameForJS . '(this)';
- $onBlur = $element->getAttribute('onBlur');
- $onChange = $element->getAttribute('onChange');
- $element->updateAttributes(array('onBlur' => $onBlur . $valFunc,
- 'onChange' => $onChange . $valFunc));
- } else { // group
- $elements =& $element->getElements();
- for ($i = 0; $i < count($elements); $i++) {
- // $groupElementName is a substring of attribute name of the element
- if (strpos($elements[$i]->getAttribute('name'), $groupElementName) === 0) {
- $valFunc = 'validate_' . $id . '_' . $shortNameForJS . '(this)';
- $onBlur = $elements[$i]->getAttribute('onBlur');
- $onChange = $elements[$i]->getAttribute('onChange');
- $elements[$i]->updateAttributes(array('onBlur' => $onBlur . $valFunc,
- 'onChange' => $onChange . $valFunc));
- }
- }
- }
- }
- $js .= '
-validate_' . $id . ' = function (frm) {
- var ret = true;
-' . $validateJS . ';
- return ret;
-}
-//--><!]]></script>';
- return $js;
- } // end func getValidationScript
-
- // }}}
-
- function display() {
- $this->getValidationScript();
- return parent::display();
- }
-}
-
-?>
\ No newline at end of file
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * An abstract base class for QuickForm renderers
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Alexey Borzov <avb@php.net>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * An abstract base class for QuickForm renderers
- *
- * The class implements a Visitor design pattern
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Alexey Borzov <avb@php.net>
- * @version Release: 3.2.16
- * @since 3.0
- * @abstract
- */
-class HTML_QuickForm_Renderer
-{
- /**
- * Constructor
- *
- * @access public
- */
- function HTML_QuickForm_Renderer()
- {
- } // end constructor
-
- /**
- * Called when visiting a form, before processing any form elements
- *
- * @param HTML_QuickForm a form being visited
- * @access public
- * @return void
- * @abstract
- */
- function startForm(&$form)
- {
- return;
- } // end func startForm
-
- /**
- * Called when visiting a form, after processing all form elements
- *
- * @param HTML_QuickForm a form being visited
- * @access public
- * @return void
- * @abstract
- */
- function finishForm(&$form)
- {
- return;
- } // end func finishForm
-
- /**
- * Called when visiting a header element
- *
- * @param HTML_QuickForm_header a header element being visited
- * @access public
- * @return void
- * @abstract
- */
- function renderHeader(&$header)
- {
- return;
- } // end func renderHeader
-
- /**
- * Called when visiting an element
- *
- * @param HTML_QuickForm_element form element being visited
- * @param bool Whether an element is required
- * @param string An error message associated with an element
- * @access public
- * @return void
- * @abstract
- */
- function renderElement(&$element, $required, $error)
- {
- return;
- } // end func renderElement
-
- /**
- * Called when visiting a hidden element
- *
- * @param HTML_QuickForm_element a hidden element being visited
- * @access public
- * @return void
- * @abstract
- */
- function renderHidden(&$element)
- {
- return;
- } // end func renderHidden
-
- /**
- * Called when visiting a raw HTML/text pseudo-element
- *
- * Only implemented in Default renderer. Usage of 'html' elements is
- * discouraged, templates should be used instead.
- *
- * @param HTML_QuickForm_html a 'raw html' element being visited
- * @access public
- * @return void
- * @abstract
- */
- function renderHtml(&$data)
- {
- return;
- } // end func renderHtml
-
- /**
- * Called when visiting a group, before processing any group elements
- *
- * @param HTML_QuickForm_group A group being visited
- * @param bool Whether a group is required
- * @param string An error message associated with a group
- * @access public
- * @return void
- * @abstract
- */
- function startGroup(&$group, $required, $error)
- {
- return;
- } // end func startGroup
-
- /**
- * Called when visiting a group, after processing all group elements
- *
- * @param HTML_QuickForm_group A group being visited
- * @access public
- * @return void
- * @abstract
- */
- function finishGroup(&$group)
- {
- return;
- } // end func finishGroup
-} // end class HTML_QuickForm_Renderer
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * A concrete renderer for HTML_QuickForm, makes an array of form contents
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Alexey Borzov <avb@php.net>
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Thomas Schulz <ths@4bconsult.de>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * An abstract base class for QuickForm renderers
- */
-require_once 'HTML/QuickForm/Renderer.php';
-
-/**
- * A concrete renderer for HTML_QuickForm, makes an array of form contents
- *
- * Based on old HTML_QuickForm::toArray() code.
- *
- * The form array structure is the following:
- * <pre>
- * array(
- * 'frozen' => 'whether the form is frozen',
- * 'javascript' => 'javascript for client-side validation',
- * 'attributes' => 'attributes for <form> tag',
- * 'requirednote => 'note about the required elements',
- * // if we set the option to collect hidden elements
- * 'hidden' => 'collected html of all hidden elements',
- * // if there were some validation errors:
- * 'errors' => array(
- * '1st element name' => 'Error for the 1st element',
- * ...
- * 'nth element name' => 'Error for the nth element'
- * ),
- * // if there are no headers in the form:
- * 'elements' => array(
- * element_1,
- * ...
- * element_N
- * )
- * // if there are headers in the form:
- * 'sections' => array(
- * array(
- * 'header' => 'Header text for the first header',
- * 'name' => 'Header name for the first header',
- * 'elements' => array(
- * element_1,
- * ...
- * element_K1
- * )
- * ),
- * ...
- * array(
- * 'header' => 'Header text for the Mth header',
- * 'name' => 'Header name for the Mth header',
- * 'elements' => array(
- * element_1,
- * ...
- * element_KM
- * )
- * )
- * )
- * );
- * </pre>
- *
- * where element_i is an array of the form:
- * <pre>
- * array(
- * 'name' => 'element name',
- * 'value' => 'element value',
- * 'type' => 'type of the element',
- * 'frozen' => 'whether element is frozen',
- * 'label' => 'label for the element',
- * 'required' => 'whether element is required',
- * 'error' => 'error associated with the element',
- * 'style' => 'some information about element style (e.g. for Smarty)',
- * // if element is not a group
- * 'html' => 'HTML for the element'
- * // if element is a group
- * 'separator' => 'separator for group elements',
- * 'elements' => array(
- * element_1,
- * ...
- * element_N
- * )
- * );
- * </pre>
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Alexey Borzov <avb@php.net>
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Thomas Schulz <ths@4bconsult.de>
- * @version Release: 3.2.16
- * @since 3.0
- */
-class HTML_QuickForm_Renderer_Array extends HTML_QuickForm_Renderer
-{
- /**#@+
- * @access private
- */
- /**
- * An array being generated
- * @var array
- */
- var $_ary;
-
- /**
- * Number of sections in the form (i.e. number of headers in it)
- * @var integer
- */
- var $_sectionCount;
-
- /**
- * Current section number
- * @var integer
- */
- var $_currentSection;
-
- /**
- * Array representing current group
- * @var array
- */
- var $_currentGroup = null;
-
- /**
- * Additional style information for different elements
- * @var array
- */
- var $_elementStyles = array();
-
- /**
- * true: collect all hidden elements into string; false: process them as usual form elements
- * @var bool
- */
- var $_collectHidden = false;
-
- /**
- * true: render an array of labels to many labels, $key 0 named 'label', the rest "label_$key"
- * false: leave labels as defined
- * @var bool
- */
- var $_staticLabels = false;
- /**#@-*/
-
- /**
- * Constructor
- *
- * @param bool true: collect all hidden elements into string; false: process them as usual form elements
- * @param bool true: render an array of labels to many labels, $key 0 to 'label' and the oterh to "label_$key"
- * @access public
- */
- function HTML_QuickForm_Renderer_Array($collectHidden = false, $staticLabels = false)
- {
- $this->HTML_QuickForm_Renderer();
- $this->_collectHidden = $collectHidden;
- $this->_staticLabels = $staticLabels;
- } // end constructor
-
-
- /**
- * Returns the resultant array
- *
- * @access public
- * @return array
- */
- function toArray()
- {
- return $this->_ary;
- }
-
-
- function startForm(&$form)
- {
- $this->_ary = array(
- 'frozen' => $form->isFrozen(),
- 'javascript' => $form->getValidationScript(),
- 'attributes' => $form->getAttributes(true),
- 'requirednote' => $form->getRequiredNote(),
- 'errors' => array()
- );
- if ($this->_collectHidden) {
- $this->_ary['hidden'] = '';
- }
- $this->_elementIdx = 1;
- $this->_currentSection = null;
- $this->_sectionCount = 0;
- } // end func startForm
-
-
- function renderHeader(&$header)
- {
- $this->_ary['sections'][$this->_sectionCount] = array(
- 'header' => $header->toHtml(),
- 'name' => $header->getName()
- );
- $this->_currentSection = $this->_sectionCount++;
- } // end func renderHeader
-
-
- function renderElement(&$element, $required, $error)
- {
- $elAry = $this->_elementToArray($element, $required, $error);
- if (!empty($error)) {
- $this->_ary['errors'][$elAry['name']] = $error;
- }
- $this->_storeArray($elAry);
- } // end func renderElement
-
-
- function renderHidden(&$element)
- {
- if ($this->_collectHidden) {
- $this->_ary['hidden'] .= $element->toHtml() . "\n";
- } else {
- $this->renderElement($element, false, null);
- }
- } // end func renderHidden
-
-
- function startGroup(&$group, $required, $error)
- {
- $this->_currentGroup = $this->_elementToArray($group, $required, $error);
- if (!empty($error)) {
- $this->_ary['errors'][$this->_currentGroup['name']] = $error;
- }
- } // end func startGroup
-
-
- function finishGroup(&$group)
- {
- $this->_storeArray($this->_currentGroup);
- $this->_currentGroup = null;
- } // end func finishGroup
-
-
- /**
- * Creates an array representing an element
- *
- * @access private
- * @param HTML_QuickForm_element element being processed
- * @param bool Whether an element is required
- * @param string Error associated with the element
- * @return array
- */
- function _elementToArray(&$element, $required, $error)
- {
- $ret = array(
- 'name' => $element->getName(),
- 'value' => $element->getValue(),
- 'type' => $element->getType(),
- 'frozen' => $element->isFrozen(),
- 'required' => $required,
- 'error' => $error
- );
- // render label(s)
- $labels = $element->getLabel();
- if (is_array($labels) && $this->_staticLabels) {
- foreach($labels as $key => $label) {
- $key = is_int($key)? $key + 1: $key;
- if (1 === $key) {
- $ret['label'] = $label;
- } else {
- $ret['label_' . $key] = $label;
- }
- }
- } else {
- $ret['label'] = $labels;
- }
-
- // set the style for the element
- if (isset($this->_elementStyles[$ret['name']])) {
- $ret['style'] = $this->_elementStyles[$ret['name']];
- }
- if ('group' == $ret['type']) {
- $ret['separator'] = $element->_separator;
- $ret['elements'] = array();
- } else {
- $ret['html'] = $element->toHtml();
- }
- return $ret;
- }
-
-
- /**
- * Stores an array representation of an element in the form array
- *
- * @access private
- * @param array Array representation of an element
- * @return void
- */
- function _storeArray($elAry)
- {
- // where should we put this element...
- if (is_array($this->_currentGroup) && ('group' != $elAry['type'])) {
- $this->_currentGroup['elements'][] = $elAry;
- } elseif (isset($this->_currentSection)) {
- $this->_ary['sections'][$this->_currentSection]['elements'][] = $elAry;
- } else {
- $this->_ary['elements'][] = $elAry;
- }
- }
-
-
- /**
- * Sets a style to use for element rendering
- *
- * @param mixed element name or array ('element name' => 'style name')
- * @param string style name if $elementName is not an array
- * @access public
- * @return void
- */
- function setElementStyle($elementName, $styleName = null)
- {
- if (is_array($elementName)) {
- $this->_elementStyles = array_merge($this->_elementStyles, $elementName);
- } else {
- $this->_elementStyles[$elementName] = $styleName;
- }
- }
-}
-?>
\ No newline at end of file
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * A static renderer for HTML_QuickForm, makes an array of form content
- * useful for a Smarty template
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Alexey Borzov <avb@php.net>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Thomas Schulz <ths@4bconsult.de>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * A concrete renderer for HTML_QuickForm, makes an array of form contents
- */
-require_once 'HTML/QuickForm/Renderer/Array.php';
-
-/**
- * A static renderer for HTML_QuickForm, makes an array of form content
- * useful for a Smarty template
- *
- * Based on old HTML_QuickForm::toArray() code and ITStatic renderer.
- *
- * The form array structure is the following:
- * <pre>
- * Array (
- * [frozen] => whether the complete form is frozen'
- * [javascript] => javascript for client-side validation
- * [attributes] => attributes for <form> tag
- * [hidden] => html of all hidden elements
- * [requirednote] => note about the required elements
- * [errors] => Array
- * (
- * [1st_element_name] => Error for the 1st element
- * ...
- * [nth_element_name] => Error for the nth element
- * )
- *
- * [header] => Array
- * (
- * [1st_header_name] => Header text for the 1st header
- * ...
- * [nth_header_name] => Header text for the nth header
- * )
- *
- * [1st_element_name] => Array for the 1st element
- * ...
- * [nth_element_name] => Array for the nth element
- * </pre>
- *
- * where an element array has the form:
- * <pre>
- * (
- * [name] => element name
- * [value] => element value,
- * [type] => type of the element
- * [frozen] => whether element is frozen
- * [label] => label for the element
- * [required] => whether element is required
- * // if element is not a group:
- * [html] => HTML for the element
- * // if element is a group:
- * [separator] => separator for group elements
- * [1st_gitem_name] => Array for the 1st element in group
- * ...
- * [nth_gitem_name] => Array for the nth element in group
- * )
- * )
- * </pre>
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Alexey Borzov <avb@php.net>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Thomas Schulz <ths@4bconsult.de>
- * @version Release: 3.2.16
- * @since 3.0
- */
-class HTML_QuickForm_Renderer_ArraySmarty extends HTML_QuickForm_Renderer_Array
-{
- /**#@+
- * @access private
- */
- /**
- * The Smarty template engine instance
- * @var object
- */
- var $_tpl = null;
-
- /**
- * Current element index
- * @var integer
- */
- var $_elementIdx = 0;
-
- /**
- * The current element index inside a group
- * @var integer
- */
- var $_groupElementIdx = 0;
-
- /**
- * How to handle the required tag for required fields
- * @var string
- * @see setRequiredTemplate()
- */
- var $_required = '';
-
- /**
- * How to handle error messages in form validation
- * @var string
- * @see setErrorTemplate()
- */
- var $_error = '';
- /**#@-*/
-
- /**
- * Constructor
- *
- * @param Smarty reference to the Smarty template engine instance
- * @param bool true: render an array of labels to many labels, $key 0 to 'label' and the oterh to "label_$key"
- * @param bool true: collect all hidden elements into string; false: process them as usual form elements
- * @access public
- */
- function HTML_QuickForm_Renderer_ArraySmarty(&$tpl, $staticLabels = false, $collectHidden = true)
- {
- $this->HTML_QuickForm_Renderer_Array($collectHidden, $staticLabels);
- $this->_tpl =& $tpl;
- } // end constructor
-
- /**
- * Called when visiting a header element
- *
- * @param HTML_QuickForm_header header element being visited
- * @access public
- * @return void
- */
- function renderHeader(&$header)
- {
- if ($name = $header->getName()) {
- $this->_ary['header'][$name] = $header->toHtml();
- } else {
- $this->_ary['header'][$this->_sectionCount] = $header->toHtml();
- }
- $this->_currentSection = $this->_sectionCount++;
- } // end func renderHeader
-
- /**
- * Called when visiting a group, before processing any group elements
- *
- * @param HTML_QuickForm_group group being visited
- * @param bool Whether a group is required
- * @param string An error message associated with a group
- * @access public
- * @return void
- */
- function startGroup(&$group, $required, $error)
- {
- parent::startGroup($group, $required, $error);
- $this->_groupElementIdx = 1;
- } // end func startGroup
-
- /**
- * Creates an array representing an element containing
- * the key for storing this
- *
- * @access private
- * @param HTML_QuickForm_element form element being visited
- * @param bool Whether an element is required
- * @param string Error associated with the element
- * @return array
- */
- function _elementToArray(&$element, $required, $error)
- {
- $ret = parent::_elementToArray($element, $required, $error);
-
- if ('group' == $ret['type']) {
- $ret['html'] = $element->toHtml();
- // we don't need the elements, see the array structure
- unset($ret['elements']);
- }
- if (($required || $error) && !empty($this->_required)){
- $this->_renderRequired($ret['label'], $ret['html'], $required, $error);
- }
- if ($error && !empty($this->_error)) {
- $this->_renderError($ret['label'], $ret['html'], $error);
- $ret['error'] = $error;
- }
- // create keys for elements grouped by native group or name
- if (strstr($ret['name'], '[') or $this->_currentGroup) {
- // Fix for bug #8123: escape backslashes and quotes to prevent errors
- // in eval(). The code below seems to handle the case where element
- // name has unbalanced square brackets. Dunno whether we really
- // need this after the fix for #8123, but I'm wary of making big
- // changes to this code.
- preg_match('/([^]]*)\\[([^]]*)\\]/', $ret['name'], $matches);
- if (isset($matches[1])) {
- $sKeysSub = substr_replace($ret['name'], '', 0, strlen($matches[1]));
- $sKeysSub = str_replace(
- array('\\', '\'', '[' , ']', '[\'\']'),
- array('\\\\', '\\\'', '[\'', '\']', '[]' ),
- $sKeysSub
- );
- $sKeys = '[\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $matches[1]) . '\']' . $sKeysSub;
- } else {
- $sKeys = '[\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $ret['name']) . '\']';
- }
- // special handling for elements in native groups
- if ($this->_currentGroup) {
- // skip unnamed group items unless radios: no name -> no static access
- // identification: have the same key string as the parent group
- if ($this->_currentGroup['keys'] == $sKeys and 'radio' != $ret['type']) {
- return false;
- }
- // reduce string of keys by remove leading group keys
- if (0 === strpos($sKeys, $this->_currentGroup['keys'])) {
- $sKeys = substr_replace($sKeys, '', 0, strlen($this->_currentGroup['keys']));
- }
- }
- // element without a name
- } elseif ($ret['name'] == '') {
- $sKeys = '[\'element_' . $this->_elementIdx . '\']';
- // other elements
- } else {
- $sKeys = '[\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $ret['name']) . '\']';
- }
- // for radios: add extra key from value
- if ('radio' == $ret['type'] and substr($sKeys, -2) != '[]') {
- $sKeys .= '[\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $ret['value']) . '\']';
- }
- $this->_elementIdx++;
- $ret['keys'] = $sKeys;
- return $ret;
- } // end func _elementToArray
-
- /**
- * Stores an array representation of an element in the form array
- *
- * @access private
- * @param array Array representation of an element
- * @return void
- */
- function _storeArray($elAry)
- {
- if ($elAry) {
- $sKeys = $elAry['keys'];
- unset($elAry['keys']);
- // where should we put this element...
- if (is_array($this->_currentGroup) && ('group' != $elAry['type'])) {
- $toEval = '$this->_currentGroup' . $sKeys . ' = $elAry;';
- } else {
- $toEval = '$this->_ary' . $sKeys . ' = $elAry;';
- }
- eval($toEval);
- }
- return;
- }
-
- /**
- * Called when an element is required
- *
- * This method will add the required tag to the element label and/or the element html
- * such as defined with the method setRequiredTemplate.
- *
- * @param string The element label
- * @param string The element html rendering
- * @param boolean The element required
- * @param string The element error
- * @see setRequiredTemplate()
- * @access private
- * @return void
- */
- function _renderRequired(&$label, &$html, &$required, &$error)
- {
- $this->_tpl->assign(array(
- 'label' => $label,
- 'html' => $html,
- 'required' => $required,
- 'error' => $error
- ));
- if (!empty($label) && strpos($this->_required, $this->_tpl->left_delimiter . '$label') !== false) {
- $label = $this->_tplFetch($this->_required);
- }
- if (!empty($html) && strpos($this->_required, $this->_tpl->left_delimiter . '$html') !== false) {
- $html = $this->_tplFetch($this->_required);
- }
- $this->_tpl->clear_assign(array('label', 'html', 'required'));
- } // end func _renderRequired
-
- /**
- * Called when an element has a validation error
- *
- * This method will add the error message to the element label or the element html
- * such as defined with the method setErrorTemplate. If the error placeholder is not found
- * in the template, the error will be displayed in the form error block.
- *
- * @param string The element label
- * @param string The element html rendering
- * @param string The element error
- * @see setErrorTemplate()
- * @access private
- * @return void
- */
- function _renderError(&$label, &$html, &$error)
- {
- $this->_tpl->assign(array('label' => '', 'html' => '', 'error' => $error));
- $error = $this->_tplFetch($this->_error);
- $this->_tpl->assign(array('label' => $label, 'html' => $html));
-
- if (!empty($label) && strpos($this->_error, $this->_tpl->left_delimiter . '$label') !== false) {
- $label = $this->_tplFetch($this->_error);
- } elseif (!empty($html) && strpos($this->_error, $this->_tpl->left_delimiter . '$html') !== false) {
- $html = $this->_tplFetch($this->_error);
- }
- $this->_tpl->clear_assign(array('label', 'html', 'error'));
- } // end func _renderError
-
- /**
- * Process an template sourced in a string with Smarty
- *
- * Smarty has no core function to render a template given as a string.
- * So we use the smarty eval plugin function to do this.
- *
- * @param string The template source
- * @access private
- * @return void
- */
- function _tplFetch($tplSource)
- {
- if (!function_exists('smarty_function_eval')) {
- require SMARTY_DIR . '/plugins/function.eval.php';
- }
- return smarty_function_eval(array('var' => $tplSource), $this->_tpl);
- }// end func _tplFetch
-
- /**
- * Sets the way required elements are rendered
- *
- * You can use {$label} or {$html} placeholders to let the renderer know where
- * where the element label or the element html are positionned according to the
- * required tag. They will be replaced accordingly with the right value. You
- * can use the full smarty syntax here, especially a custom modifier for I18N.
- * For example:
- * {if $required}<span style="color: red;">*</span>{/if}{$label|translate}
- * will put a red star in front of the label if the element is required and
- * translate the label.
- *
- *
- * @param string The required element template
- * @access public
- * @return void
- */
- function setRequiredTemplate($template)
- {
- $this->_required = $template;
- } // end func setRequiredTemplate
-
- /**
- * Sets the way elements with validation errors are rendered
- *
- * You can use {$label} or {$html} placeholders to let the renderer know where
- * where the element label or the element html are positionned according to the
- * error message. They will be replaced accordingly with the right value.
- * The error message will replace the {$error} placeholder.
- * For example:
- * {if $error}<span style="color: red;">{$error}</span>{/if}<br />{$html}
- * will put the error message in red on top of the element html.
- *
- * If you want all error messages to be output in the main error block, use
- * the {$form.errors} part of the rendered array that collects all raw error
- * messages.
- *
- * If you want to place all error messages manually, do not specify {$html}
- * nor {$label}.
- *
- * Groups can have special layouts. With this kind of groups, you have to
- * place the formated error message manually. In this case, use {$form.group.error}
- * where you want the formated error message to appear in the form.
- *
- * @param string The element error template
- * @access public
- * @return void
- */
- function setErrorTemplate($template)
- {
- $this->_error = $template;
- } // end func setErrorTemplate
-}
-?>
\ No newline at end of file
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * A concrete renderer for HTML_QuickForm, based on QuickForm 2.x built-in one
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Alexey Borzov <avb@php.net>
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * An abstract base class for QuickForm renderers
- */
-require_once 'HTML/QuickForm/Renderer.php';
-
-/**
- * A concrete renderer for HTML_QuickForm, based on QuickForm 2.x built-in one
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Alexey Borzov <avb@php.net>
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @version Release: 3.2.16
- * @since 3.0
- */
-class HTML_QuickForm_Renderer_Default extends HTML_QuickForm_Renderer
-{
- /**
- * The HTML of the form
- * @var string
- * @access private
- */
- var $_html;
-
- /**
- * Header Template string
- * @var string
- * @access private
- */
- var $_headerTemplate =
- "\n\t<tr>\n\t\t<td style=\"white-space: nowrap; background-color: #CCCCCC;\" align=\"left\" valign=\"top\" colspan=\"2\"><b>{header}</b></td>\n\t</tr>";
-
- /**
- * Element template string
- * @var string
- * @access private
- */
- var $_elementTemplate =
- "\n\t<tr>\n\t\t<td align=\"right\" valign=\"top\"><!-- BEGIN required --><span style=\"color: #ff0000\">*</span><!-- END required --><b>{label}</b></td>\n\t\t<td valign=\"top\" align=\"left\"><!-- BEGIN error --><span style=\"color: #ff0000\">{error}</span><br /><!-- END error -->\t{element}</td>\n\t</tr>";
-
- /**
- * Form template string
- * @var string
- * @access private
- */
- var $_formTemplate =
- "\n<form{attributes}>\n<div>\n{hidden}<table border=\"0\">\n{content}\n</table>\n</div>\n</form>";
-
- /**
- * Required Note template string
- * @var string
- * @access private
- */
- var $_requiredNoteTemplate =
- "\n\t<tr>\n\t\t<td></td>\n\t<td align=\"left\" valign=\"top\">{requiredNote}</td>\n\t</tr>";
-
- /**
- * Array containing the templates for customised elements
- * @var array
- * @access private
- */
- var $_templates = array();
-
- /**
- * Array containing the templates for group wraps.
- *
- * These templates are wrapped around group elements and groups' own
- * templates wrap around them. This is set by setGroupTemplate().
- *
- * @var array
- * @access private
- */
- var $_groupWraps = array();
-
- /**
- * Array containing the templates for elements within groups
- * @var array
- * @access private
- */
- var $_groupTemplates = array();
-
- /**
- * True if we are inside a group
- * @var bool
- * @access private
- */
- var $_inGroup = false;
-
- /**
- * Array with HTML generated for group elements
- * @var array
- * @access private
- */
- var $_groupElements = array();
-
- /**
- * Template for an element inside a group
- * @var string
- * @access private
- */
- var $_groupElementTemplate = '';
-
- /**
- * HTML that wraps around the group elements
- * @var string
- * @access private
- */
- var $_groupWrap = '';
-
- /**
- * HTML for the current group
- * @var string
- * @access private
- */
- var $_groupTemplate = '';
-
- /**
- * Collected HTML of the hidden fields
- * @var string
- * @access private
- */
- var $_hiddenHtml = '';
-
- /**
- * Constructor
- *
- * @access public
- */
- function HTML_QuickForm_Renderer_Default()
- {
- $this->HTML_QuickForm_Renderer();
- } // end constructor
-
- /**
- * returns the HTML generated for the form
- *
- * @access public
- * @return string
- */
- function toHtml()
- {
- // _hiddenHtml is cleared in finishForm(), so this only matters when
- // finishForm() was not called (e.g. group::toHtml(), bug #3511)
- return $this->_hiddenHtml . $this->_html;
- } // end func toHtml
-
- /**
- * Called when visiting a form, before processing any form elements
- *
- * @param HTML_QuickForm form object being visited
- * @access public
- * @return void
- */
- function startForm(&$form)
- {
- $this->_html = '';
- $this->_hiddenHtml = '';
- } // end func startForm
-
- /**
- * Called when visiting a form, after processing all form elements
- * Adds required note, form attributes, validation javascript and form content.
- *
- * @param HTML_QuickForm form object being visited
- * @access public
- * @return void
- */
- function finishForm(&$form)
- {
- // add a required note, if one is needed
- if (!empty($form->_required) && !$form->_freezeAll) {
- $this->_html .= str_replace('{requiredNote}', $form->getRequiredNote(), $this->_requiredNoteTemplate);
- }
- // add form attributes and content
- $html = str_replace('{attributes}', $form->getAttributes(true), $this->_formTemplate);
- if (strpos($this->_formTemplate, '{hidden}')) {
- $html = str_replace('{hidden}', $this->_hiddenHtml, $html);
- } else {
- $this->_html .= $this->_hiddenHtml;
- }
- $this->_hiddenHtml = '';
- $this->_html = str_replace('{content}', $this->_html, $html);
- // add a validation script
- if ('' != ($script = $form->getValidationScript())) {
- $this->_html = $script . "\n" . $this->_html;
- }
- } // end func finishForm
-
- /**
- * Called when visiting a header element
- *
- * @param HTML_QuickForm_header header element being visited
- * @access public
- * @return void
- */
- function renderHeader(&$header)
- {
- $name = $header->getName();
- if (!empty($name) && isset($this->_templates[$name])) {
- $this->_html .= str_replace('{header}', $header->toHtml(), $this->_templates[$name]);
- } else {
- $this->_html .= str_replace('{header}', $header->toHtml(), $this->_headerTemplate);
- }
- } // end func renderHeader
-
- /**
- * Helper method for renderElement
- *
- * @param string Element name
- * @param mixed Element label (if using an array of labels, you should set the appropriate template)
- * @param bool Whether an element is required
- * @param string Error message associated with the element
- * @access private
- * @see renderElement()
- * @return string Html for element
- */
- function _prepareTemplate($name, $label, $required, $error)
- {
- if (is_array($label)) {
- $nameLabel = array_shift($label);
- } else {
- $nameLabel = $label;
- }
- if (isset($this->_templates[$name])) {
- $html = str_replace('{label}', $nameLabel, $this->_templates[$name]);
- } else {
- $html = str_replace('{label}', $nameLabel, $this->_elementTemplate);
- }
- if ($required) {
- $html = str_replace('<!-- BEGIN required -->', '', $html);
- $html = str_replace('<!-- END required -->', '', $html);
- } else {
- $html = preg_replace("/([ \t\n\r]*)?<!-- BEGIN required -->.*<!-- END required -->([ \t\n\r]*)?/isU", '', $html);
- }
- if (isset($error)) {
- $html = str_replace('{error}', $error, $html);
- $html = str_replace('<!-- BEGIN error -->', '', $html);
- $html = str_replace('<!-- END error -->', '', $html);
- } else {
- $html = preg_replace("/([ \t\n\r]*)?<!-- BEGIN error -->.*<!-- END error -->([ \t\n\r]*)?/isU", '', $html);
- }
- if (is_array($label)) {
- foreach($label as $key => $text) {
- $key = is_int($key)? $key + 2: $key;
- $html = str_replace("{label_{$key}}", $text, $html);
- $html = str_replace("<!-- BEGIN label_{$key} -->", '', $html);
- $html = str_replace("<!-- END label_{$key} -->", '', $html);
- }
- }
- if (strpos($html, '{label_')) {
- $html = preg_replace('/\s*<!-- BEGIN label_(\S+) -->.*<!-- END label_\1 -->\s*/is', '', $html);
- }
- return $html;
- } // end func _prepareTemplate
-
- /**
- * Renders an element Html
- * Called when visiting an element
- *
- * @param HTML_QuickForm_element form element being visited
- * @param bool Whether an element is required
- * @param string An error message associated with an element
- * @access public
- * @return void
- */
- function renderElement(&$element, $required, $error)
- {
- if (!$this->_inGroup) {
- $html = $this->_prepareTemplate($element->getName(), $element->getLabel(), $required, $error);
- $this->_html .= str_replace('{element}', $element->toHtml(), $html);
-
- } elseif (!empty($this->_groupElementTemplate)) {
- $html = str_replace('{label}', $element->getLabel(), $this->_groupElementTemplate);
- if ($required) {
- $html = str_replace('<!-- BEGIN required -->', '', $html);
- $html = str_replace('<!-- END required -->', '', $html);
- } else {
- $html = preg_replace("/([ \t\n\r]*)?<!-- BEGIN required -->.*<!-- END required -->([ \t\n\r]*)?/isU", '', $html);
- }
- $this->_groupElements[] = str_replace('{element}', $element->toHtml(), $html);
-
- } else {
- $this->_groupElements[] = $element->toHtml();
- }
- } // end func renderElement
-
- /**
- * Renders an hidden element
- * Called when visiting a hidden element
- *
- * @param HTML_QuickForm_element form element being visited
- * @access public
- * @return void
- */
- function renderHidden(&$element)
- {
- $this->_hiddenHtml .= $element->toHtml() . "\n";
- } // end func renderHidden
-
- /**
- * Called when visiting a raw HTML/text pseudo-element
- *
- * @param HTML_QuickForm_html element being visited
- * @access public
- * @return void
- */
- function renderHtml(&$data)
- {
- $this->_html .= $data->toHtml();
- } // end func renderHtml
-
- /**
- * Called when visiting a group, before processing any group elements
- *
- * @param HTML_QuickForm_group group being visited
- * @param bool Whether a group is required
- * @param string An error message associated with a group
- * @access public
- * @return void
- */
- function startGroup(&$group, $required, $error)
- {
- $name = $group->getName();
- $this->_groupTemplate = $this->_prepareTemplate($name, $group->getLabel(), $required, $error);
- $this->_groupElementTemplate = empty($this->_groupTemplates[$name])? '': $this->_groupTemplates[$name];
- $this->_groupWrap = empty($this->_groupWraps[$name])? '': $this->_groupWraps[$name];
- $this->_groupElements = array();
- $this->_inGroup = true;
- } // end func startGroup
-
- /**
- * Called when visiting a group, after processing all group elements
- *
- * @param HTML_QuickForm_group group being visited
- * @access public
- * @return void
- */
- function finishGroup(&$group)
- {
- $separator = $group->_separator;
- if (is_array($separator)) {
- $count = count($separator);
- $html = '';
- for ($i = 0; $i < count($this->_groupElements); $i++) {
- $html .= (0 == $i? '': $separator[($i - 1) % $count]) . $this->_groupElements[$i];
- }
- } else {
- if (is_null($separator)) {
- $separator = ' ';
- }
- $html = implode((string)$separator, $this->_groupElements);
- }
- if (!empty($this->_groupWrap)) {
- $html = str_replace('{content}', $html, $this->_groupWrap);
- }
- $this->_html .= str_replace('{element}', $html, $this->_groupTemplate);
- $this->_inGroup = false;
- } // end func finishGroup
-
- /**
- * Sets element template
- *
- * @param string The HTML surrounding an element
- * @param string (optional) Name of the element to apply template for
- * @access public
- * @return void
- */
- function setElementTemplate($html, $element = null)
- {
- if (is_null($element)) {
- $this->_elementTemplate = $html;
- } else {
- $this->_templates[$element] = $html;
- }
- } // end func setElementTemplate
-
-
- /**
- * Sets template for a group wrapper
- *
- * This template is contained within a group-as-element template
- * set via setTemplate() and contains group's element templates, set
- * via setGroupElementTemplate()
- *
- * @param string The HTML surrounding group elements
- * @param string Name of the group to apply template for
- * @access public
- * @return void
- */
- function setGroupTemplate($html, $group)
- {
- $this->_groupWraps[$group] = $html;
- } // end func setGroupTemplate
-
- /**
- * Sets element template for elements within a group
- *
- * @param string The HTML surrounding an element
- * @param string Name of the group to apply template for
- * @access public
- * @return void
- */
- function setGroupElementTemplate($html, $group)
- {
- $this->_groupTemplates[$group] = $html;
- } // end func setGroupElementTemplate
-
- /**
- * Sets header template
- *
- * @param string The HTML surrounding the header
- * @access public
- * @return void
- */
- function setHeaderTemplate($html)
- {
- $this->_headerTemplate = $html;
- } // end func setHeaderTemplate
-
- /**
- * Sets form template
- *
- * @param string The HTML surrounding the form tags
- * @access public
- * @return void
- */
- function setFormTemplate($html)
- {
- $this->_formTemplate = $html;
- } // end func setFormTemplate
-
- /**
- * Sets the note indicating required fields template
- *
- * @param string The HTML surrounding the required note
- * @access public
- * @return void
- */
- function setRequiredNoteTemplate($html)
- {
- $this->_requiredNoteTemplate = $html;
- } // end func setRequiredNoteTemplate
-
- /**
- * Clears all the HTML out of the templates that surround notes, elements, etc.
- * Useful when you want to use addData() to create a completely custom form look
- *
- * @access public
- * @return void
- */
- function clearAllTemplates()
- {
- $this->setElementTemplate('{element}');
- $this->setFormTemplate("\n\t<form{attributes}>{content}\n\t</form>\n");
- $this->setRequiredNoteTemplate('');
- $this->_templates = array();
- } // end func clearAllTemplates
-} // end class HTML_QuickForm_Renderer_Default
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * A concrete renderer for HTML_QuickForm, using Integrated Templates.
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Alexey Borzov <avb@php.net>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * An abstract base class for QuickForm renderers
- */
-require_once 'HTML/QuickForm/Renderer.php';
-
-/**
- * A concrete renderer for HTML_QuickForm, using Integrated Templates.
- *
- * This is a "dynamic" renderer, which means that concrete form look
- * is defined at runtime. This also means that you can define
- * <b>one</b> template file for <b>all</b> your forms. That template
- * should contain a block for every element 'look' appearing in your
- * forms and also some special blocks (consult the examples). If a
- * special block is not set for an element, the renderer falls back to
- * a default one.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Alexey Borzov <avb@php.net>
- * @version Release: 3.2.16
- * @since 3.0
- */
-class HTML_QuickForm_Renderer_ITDynamic extends HTML_QuickForm_Renderer
-{
- /**#@+
- * @access private
- */
- /**
- * A template class (HTML_Template_ITX or HTML_Template_Sigma) instance
- * @var HTML_Template_ITX|HTML_Template_Sigma
- */
- var $_tpl = null;
-
- /**
- * The errors that were not shown near concrete fields go here
- * @var array
- */
- var $_errors = array();
-
- /**
- * Show the block with required note?
- * @var bool
- */
- var $_showRequired = false;
-
- /**
- * A separator for group elements
- * @var mixed
- */
- var $_groupSeparator = null;
-
- /**
- * The current element index inside a group
- * @var integer
- */
- var $_groupElementIdx = 0;
-
- /**
- * Blocks to use for different elements
- * @var array
- */
- var $_elementBlocks = array();
-
- /**
- * Block to use for headers
- * @var string
- */
- var $_headerBlock = null;
- /**#@-*/
-
-
- /**
- * Constructor
- *
- * @param HTML_Template_ITX|HTML_Template_Sigma Template object to use
- */
- function HTML_QuickForm_Renderer_ITDynamic(&$tpl)
- {
- $this->HTML_QuickForm_Renderer();
- $this->_tpl =& $tpl;
- $this->_tpl->setCurrentBlock('qf_main_loop');
- }
-
-
- function finishForm(&$form)
- {
- // display errors above form
- if (!empty($this->_errors) && $this->_tpl->blockExists('qf_error_loop')) {
- foreach ($this->_errors as $error) {
- $this->_tpl->setVariable('qf_error', $error);
- $this->_tpl->parse('qf_error_loop');
- }
- }
- // show required note
- if ($this->_showRequired) {
- $this->_tpl->setVariable('qf_required_note', $form->getRequiredNote());
- }
- // assign form attributes
- $this->_tpl->setVariable('qf_attributes', $form->getAttributes(true));
- // assign javascript validation rules
- $this->_tpl->setVariable('qf_javascript', $form->getValidationScript());
- }
-
-
- function renderHeader(&$header)
- {
- $blockName = $this->_matchBlock($header);
- if ('qf_header' == $blockName && isset($this->_headerBlock)) {
- $blockName = $this->_headerBlock;
- }
- $this->_tpl->setVariable('qf_header', $header->toHtml());
- $this->_tpl->parse($blockName);
- $this->_tpl->parse('qf_main_loop');
- }
-
-
- function renderElement(&$element, $required, $error)
- {
- $blockName = $this->_matchBlock($element);
- // are we inside a group?
- if ('qf_main_loop' != $this->_tpl->currentBlock) {
- if (0 != $this->_groupElementIdx && $this->_tpl->placeholderExists('qf_separator', $blockName)) {
- if (is_array($this->_groupSeparator)) {
- $this->_tpl->setVariable('qf_separator', $this->_groupSeparator[($this->_groupElementIdx - 1) % count($this->_groupSeparator)]);
- } else {
- $this->_tpl->setVariable('qf_separator', (string)$this->_groupSeparator);
- }
- }
- $this->_groupElementIdx++;
-
- } elseif(!empty($error)) {
- // show the error message or keep it for later use
- if ($this->_tpl->blockExists($blockName . '_error')) {
- $this->_tpl->setVariable('qf_error', $error);
- } else {
- $this->_errors[] = $error;
- }
- }
- // show an '*' near the required element
- if ($required) {
- $this->_showRequired = true;
- if ($this->_tpl->blockExists($blockName . '_required')) {
- $this->_tpl->touchBlock($blockName . '_required');
- }
- }
- // Prepare multiple labels
- $labels = $element->getLabel();
- if (is_array($labels)) {
- $mainLabel = array_shift($labels);
- } else {
- $mainLabel = $labels;
- }
- // render the element itself with its main label
- $this->_tpl->setVariable('qf_element', $element->toHtml());
- if ($this->_tpl->placeholderExists('qf_label', $blockName)) {
- $this->_tpl->setVariable('qf_label', $mainLabel);
- }
- // render extra labels, if any
- if (is_array($labels)) {
- foreach($labels as $key => $label) {
- $key = is_int($key)? $key + 2: $key;
- if ($this->_tpl->blockExists($blockName . '_label_' . $key)) {
- $this->_tpl->setVariable('qf_label_' . $key, $label);
- }
- }
- }
- $this->_tpl->parse($blockName);
- $this->_tpl->parseCurrentBlock();
- }
-
-
- function renderHidden(&$element)
- {
- $this->_tpl->setVariable('qf_hidden', $element->toHtml());
- $this->_tpl->parse('qf_hidden_loop');
- }
-
-
- function startGroup(&$group, $required, $error)
- {
- $blockName = $this->_matchBlock($group);
- $this->_tpl->setCurrentBlock($blockName . '_loop');
- $this->_groupElementIdx = 0;
- $this->_groupSeparator = is_null($group->_separator)? ' ': $group->_separator;
- // show an '*' near the required element
- if ($required) {
- $this->_showRequired = true;
- if ($this->_tpl->blockExists($blockName . '_required')) {
- $this->_tpl->touchBlock($blockName . '_required');
- }
- }
- // show the error message or keep it for later use
- if (!empty($error)) {
- if ($this->_tpl->blockExists($blockName . '_error')) {
- $this->_tpl->setVariable('qf_error', $error);
- } else {
- $this->_errors[] = $error;
- }
- }
- $this->_tpl->setVariable('qf_group_label', $group->getLabel());
- }
-
-
- function finishGroup(&$group)
- {
- $this->_tpl->parse($this->_matchBlock($group));
- $this->_tpl->setCurrentBlock('qf_main_loop');
- $this->_tpl->parseCurrentBlock();
- }
-
-
- /**
- * Returns the name of a block to use for element rendering
- *
- * If a name was not explicitly set via setElementBlock(), it tries
- * the names '{prefix}_{element type}' and '{prefix}_{element}', where
- * prefix is either 'qf' or the name of the current group's block
- *
- * @param HTML_QuickForm_element form element being rendered
- * @access private
- * @return string block name
- */
- function _matchBlock(&$element)
- {
- $name = $element->getName();
- $type = $element->getType();
- if (isset($this->_elementBlocks[$name]) && $this->_tpl->blockExists($this->_elementBlocks[$name])) {
- if (('group' == $type) || ($this->_elementBlocks[$name] . '_loop' != $this->_tpl->currentBlock)) {
- return $this->_elementBlocks[$name];
- }
- }
- if ('group' != $type && 'qf_main_loop' != $this->_tpl->currentBlock) {
- $prefix = substr($this->_tpl->currentBlock, 0, -5); // omit '_loop' postfix
- } else {
- $prefix = 'qf';
- }
- if ($this->_tpl->blockExists($prefix . '_' . $type)) {
- return $prefix . '_' . $type;
- } elseif ($this->_tpl->blockExists($prefix . '_' . $name)) {
- return $prefix . '_' . $name;
- } else {
- return $prefix . '_element';
- }
- }
-
-
- /**
- * Sets the block to use for element rendering
- *
- * @param mixed element name or array ('element name' => 'block name')
- * @param string block name if $elementName is not an array
- * @access public
- * @return void
- */
- function setElementBlock($elementName, $blockName = null)
- {
- if (is_array($elementName)) {
- $this->_elementBlocks = array_merge($this->_elementBlocks, $elementName);
- } else {
- $this->_elementBlocks[$elementName] = $blockName;
- }
- }
-
-
- /**
- * Sets the name of a block to use for header rendering
- *
- * @param string block name
- * @access public
- * @return void
- */
- function setHeaderBlock($blockName)
- {
- $this->_headerBlock = $blockName;
- }
-}
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * A static renderer for HTML_QuickForm compatible
- * with HTML_Template_IT and HTML_Template_Sigma.
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * An abstract base class for QuickForm renderers
- */
-require_once 'HTML/QuickForm/Renderer.php';
-
-/**
- * A static renderer for HTML_QuickForm compatible
- * with HTML_Template_IT and HTML_Template_Sigma.
- *
- * As opposed to the dynamic renderer, this renderer needs
- * every elements and labels in the form to be specified by
- * placeholders at the position you want them to be displayed.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @version Release: 3.2.16
- * @since 3.0
- */
-class HTML_QuickForm_Renderer_ITStatic extends HTML_QuickForm_Renderer
-{
- /**#@+
- * @access private
- */
- /**
- * An HTML_Template_IT or some other API compatible Template instance
- * @var object
- */
- var $_tpl = null;
-
- /**
- * Rendered form name
- * @var string
- */
- var $_formName = 'form';
-
- /**
- * The errors that were not shown near concrete fields go here
- * @var array
- */
- var $_errors = array();
-
- /**
- * Show the block with required note?
- * @var bool
- */
- var $_showRequired = false;
-
- /**
- * Which group are we currently parsing ?
- * @var string
- */
- var $_inGroup;
-
- /**
- * Index of the element in its group
- * @var int
- */
- var $_elementIndex = 0;
-
- /**
- * If elements have been added with the same name
- * @var array
- */
- var $_duplicateElements = array();
-
- /**
- * How to handle the required tag for required fields
- * @var string
- */
- var $_required = '{label}<font size="1" color="red">*</font>';
-
- /**
- * How to handle error messages in form validation
- * @var string
- */
- var $_error = '<font color="red">{error}</font><br />{html}';
-
- /**
- * Collected HTML for hidden elements, if needed
- * @var string
- */
- var $_hidden = '';
- /**#@-*/
-
- /**
- * Constructor
- *
- * @param HTML_Template_IT|HTML_Template_Sigma Template object to use
- */
- function HTML_QuickForm_Renderer_ITStatic(&$tpl)
- {
- $this->HTML_QuickForm_Renderer();
- $this->_tpl =& $tpl;
- } // end constructor
-
- /**
- * Called when visiting a form, before processing any form elements
- *
- * @param HTML_QuickForm form object being visited
- * @access public
- * @return void
- */
- function startForm(&$form)
- {
- $this->_formName = $form->getAttribute('id');
-
- if (count($form->_duplicateIndex) > 0) {
- // Take care of duplicate elements
- foreach ($form->_duplicateIndex as $elementName => $indexes) {
- $this->_duplicateElements[$elementName] = 0;
- }
- }
- } // end func startForm
-
- /**
- * Called when visiting a form, after processing all form elements
- *
- * @param HTML_QuickForm form object being visited
- * @access public
- * @return void
- */
- function finishForm(&$form)
- {
- // display errors above form
- if (!empty($this->_errors) && $this->_tpl->blockExists($this->_formName.'_error_loop')) {
- foreach ($this->_errors as $error) {
- $this->_tpl->setVariable($this->_formName.'_error', $error);
- $this->_tpl->parse($this->_formName.'_error_loop');
- }
- }
- // show required note
- if ($this->_showRequired) {
- $this->_tpl->setVariable($this->_formName.'_required_note', $form->getRequiredNote());
- }
- // add hidden elements, if collected
- if (!empty($this->_hidden)) {
- $this->_tpl->setVariable($this->_formName . '_hidden', $this->_hidden);
- }
- // assign form attributes
- $this->_tpl->setVariable($this->_formName.'_attributes', $form->getAttributes(true));
- // assign javascript validation rules
- $this->_tpl->setVariable($this->_formName.'_javascript', $form->getValidationScript());
- } // end func finishForm
-
- /**
- * Called when visiting a header element
- *
- * @param HTML_QuickForm_header header element being visited
- * @access public
- * @return void
- */
- function renderHeader(&$header)
- {
- $name = $header->getName();
- $varName = $this->_formName.'_header';
-
- // Find placeHolder
- if (!empty($name) && $this->_tpl->placeHolderExists($this->_formName.'_header_'.$name)) {
- $varName = $this->_formName.'_header_'.$name;
- }
- $this->_tpl->setVariable($varName, $header->toHtml());
- } // end func renderHeader
-
- /**
- * Called when visiting an element
- *
- * @param HTML_QuickForm_element form element being visited
- * @param bool Whether an element is required
- * @param string An error message associated with an element
- * @access public
- * @return void
- */
- function renderElement(&$element, $required, $error)
- {
- $name = $element->getName();
-
- // are we inside a group?
- if (!empty($this->_inGroup)) {
- $varName = $this->_formName.'_'.str_replace(array('[', ']'), '_', $name);
- if (substr($varName, -2) == '__') {
- // element name is of type : group[]
- $varName = $this->_inGroup.'_'.$this->_elementIndex.'_';
- $this->_elementIndex++;
- }
- if ($varName != $this->_inGroup) {
- $varName .= '_' == substr($varName, -1)? '': '_';
- // element name is of type : group[name]
- $label = $element->getLabel();
- $html = $element->toHtml();
-
- if ($required && !$element->isFrozen()) {
- $this->_renderRequired($label, $html);
- $this->_showRequired = true;
- }
- if (!empty($label)) {
- if (is_array($label)) {
- foreach ($label as $key => $value) {
- $this->_tpl->setVariable($varName.'label_'.$key, $value);
- }
- } else {
- $this->_tpl->setVariable($varName.'label', $label);
- }
- }
- $this->_tpl->setVariable($varName.'html', $html);
- }
-
- } else {
-
- $name = str_replace(array('[', ']'), array('_', ''), $name);
-
- if (isset($this->_duplicateElements[$name])) {
- // Element is a duplicate
- $varName = $this->_formName.'_'.$name.'_'.$this->_duplicateElements[$name];
- $this->_duplicateElements[$name]++;
- } else {
- $varName = $this->_formName.'_'.$name;
- }
-
- $label = $element->getLabel();
- $html = $element->toHtml();
-
- if ($required) {
- $this->_showRequired = true;
- $this->_renderRequired($label, $html);
- }
- if (!empty($error)) {
- $this->_renderError($label, $html, $error);
- }
- if (is_array($label)) {
- foreach ($label as $key => $value) {
- $this->_tpl->setVariable($varName.'_label_'.$key, $value);
- }
- } else {
- $this->_tpl->setVariable($varName.'_label', $label);
- }
- $this->_tpl->setVariable($varName.'_html', $html);
- }
- } // end func renderElement
-
- /**
- * Called when visiting a hidden element
- *
- * @param HTML_QuickForm_element hidden element being visited
- * @access public
- * @return void
- */
- function renderHidden(&$element)
- {
- if ($this->_tpl->placeholderExists($this->_formName . '_hidden')) {
- $this->_hidden .= $element->toHtml();
- } else {
- $name = $element->getName();
- $name = str_replace(array('[', ']'), array('_', ''), $name);
- $this->_tpl->setVariable($this->_formName.'_'.$name.'_html', $element->toHtml());
- }
- } // end func renderHidden
-
- /**
- * Called when visiting a group, before processing any group elements
- *
- * @param HTML_QuickForm_group group being visited
- * @param bool Whether a group is required
- * @param string An error message associated with a group
- * @access public
- * @return void
- */
- function startGroup(&$group, $required, $error)
- {
- $name = $group->getName();
- $varName = $this->_formName.'_'.$name;
-
- $this->_elementIndex = 0;
-
- $html = $this->_tpl->placeholderExists($varName.'_html') ? $group->toHtml() : '';
- $label = $group->getLabel();
-
- if ($required) {
- $this->_renderRequired($label, $html);
- }
- if (!empty($error)) {
- $this->_renderError($label, $html, $error);
- }
- if (!empty($html)) {
- $this->_tpl->setVariable($varName.'_html', $html);
- } else {
- // Uses error blocks to set the special groups layout error
- // <!-- BEGIN form_group_error -->{form_group_error}<!-- END form_group_error -->
- if (!empty($error)) {
- if ($this->_tpl->placeholderExists($varName.'_error')) {
- if ($this->_tpl->blockExists($this->_formName . '_error_block')) {
- $this->_tpl->setVariable($this->_formName . '_error', $error);
- $error = $this->_getTplBlock($this->_formName . '_error_block');
- } elseif (strpos($this->_error, '{html}') !== false || strpos($this->_error, '{label}') !== false) {
- $error = str_replace('{error}', $error, $this->_error);
- }
- }
- $this->_tpl->setVariable($varName . '_error', $error);
- array_pop($this->_errors);
- }
- }
- if (is_array($label)) {
- foreach ($label as $key => $value) {
- $this->_tpl->setVariable($varName.'_label_'.$key, $value);
- }
- } else {
- $this->_tpl->setVariable($varName.'_label', $label);
- }
- $this->_inGroup = $varName;
- } // end func startGroup
-
- /**
- * Called when visiting a group, after processing all group elements
- *
- * @param HTML_QuickForm_group group being visited
- * @access public
- * @return void
- */
- function finishGroup(&$group)
- {
- $this->_inGroup = '';
- } // end func finishGroup
-
- /**
- * Sets the way required elements are rendered
- *
- * You can use {label} or {html} placeholders to let the renderer know where
- * where the element label or the element html are positionned according to the
- * required tag. They will be replaced accordingly with the right value.
- * For example:
- * <font color="red">*</font>{label}
- * will put a red star in front of the label if the element is required.
- *
- * @param string The required element template
- * @access public
- * @return void
- */
- function setRequiredTemplate($template)
- {
- $this->_required = $template;
- } // end func setRequiredTemplate
-
- /**
- * Sets the way elements with validation errors are rendered
- *
- * You can use {label} or {html} placeholders to let the renderer know where
- * where the element label or the element html are positionned according to the
- * error message. They will be replaced accordingly with the right value.
- * The error message will replace the {error} place holder.
- * For example:
- * <font color="red">{error}</font><br />{html}
- * will put the error message in red on top of the element html.
- *
- * If you want all error messages to be output in the main error block, do not specify
- * {html} nor {label}.
- *
- * Groups can have special layouts. With this kind of groups, the renderer will need
- * to know where to place the error message. In this case, use error blocks like:
- * <!-- BEGIN form_group_error -->{form_group_error}<!-- END form_group_error -->
- * where you want the error message to appear in the form.
- *
- * @param string The element error template
- * @access public
- * @return void
- */
- function setErrorTemplate($template)
- {
- $this->_error = $template;
- } // end func setErrorTemplate
-
- /**
- * Called when an element is required
- *
- * This method will add the required tag to the element label and/or the element html
- * such as defined with the method setRequiredTemplate
- *
- * @param string The element label
- * @param string The element html rendering
- * @see setRequiredTemplate()
- * @access private
- * @return void
- */
- function _renderRequired(&$label, &$html)
- {
- if ($this->_tpl->blockExists($tplBlock = $this->_formName . '_required_block')) {
- if (!empty($label) && $this->_tpl->placeholderExists($this->_formName . '_label', $tplBlock)) {
- $this->_tpl->setVariable($this->_formName . '_label', is_array($label)? $label[0]: $label);
- if (is_array($label)) {
- $label[0] = $this->_getTplBlock($tplBlock);
- } else {
- $label = $this->_getTplBlock($tplBlock);
- }
- }
- if (!empty($html) && $this->_tpl->placeholderExists($this->_formName . '_html', $tplBlock)) {
- $this->_tpl->setVariable($this->_formName . '_html', $html);
- $html = $this->_getTplBlock($tplBlock);
- }
- } else {
- if (!empty($label) && strpos($this->_required, '{label}') !== false) {
- if (is_array($label)) {
- $label[0] = str_replace('{label}', $label[0], $this->_required);
- } else {
- $label = str_replace('{label}', $label, $this->_required);
- }
- }
- if (!empty($html) && strpos($this->_required, '{html}') !== false) {
- $html = str_replace('{html}', $html, $this->_required);
- }
- }
- } // end func _renderRequired
-
- /**
- * Called when an element has a validation error
- *
- * This method will add the error message to the element label or the element html
- * such as defined with the method setErrorTemplate. If the error placeholder is not found
- * in the template, the error will be displayed in the form error block.
- *
- * @param string The element label
- * @param string The element html rendering
- * @param string The element error
- * @see setErrorTemplate()
- * @access private
- * @return void
- */
- function _renderError(&$label, &$html, $error)
- {
- if ($this->_tpl->blockExists($tplBlock = $this->_formName . '_error_block')) {
- $this->_tpl->setVariable($this->_formName . '_error', $error);
- if (!empty($label) && $this->_tpl->placeholderExists($this->_formName . '_label', $tplBlock)) {
- $this->_tpl->setVariable($this->_formName . '_label', is_array($label)? $label[0]: $label);
- if (is_array($label)) {
- $label[0] = $this->_getTplBlock($tplBlock);
- } else {
- $label = $this->_getTplBlock($tplBlock);
- }
- } elseif (!empty($html) && $this->_tpl->placeholderExists($this->_formName . '_html', $tplBlock)) {
- $this->_tpl->setVariable($this->_formName . '_html', $html);
- $html = $this->_getTplBlock($tplBlock);
- }
- // clean up after ourselves
- $this->_tpl->setVariable($this->_formName . '_error', null);
- } elseif (!empty($label) && strpos($this->_error, '{label}') !== false) {
- if (is_array($label)) {
- $label[0] = str_replace(array('{label}', '{error}'), array($label[0], $error), $this->_error);
- } else {
- $label = str_replace(array('{label}', '{error}'), array($label, $error), $this->_error);
- }
- } elseif (!empty($html) && strpos($this->_error, '{html}') !== false) {
- $html = str_replace(array('{html}', '{error}'), array($html, $error), $this->_error);
- } else {
- $this->_errors[] = $error;
- }
- }// end func _renderError
-
-
- /**
- * Returns the block's contents
- *
- * The method is needed because ITX and Sigma implement clearing
- * the block contents on get() a bit differently
- *
- * @param string Block name
- * @return string Block contents
- */
- function _getTplBlock($block)
- {
- $this->_tpl->parse($block);
- if (is_a($this->_tpl, 'html_template_sigma')) {
- $ret = $this->_tpl->get($block, true);
- } else {
- $oldClear = $this->_tpl->clearCache;
- $this->_tpl->clearCache = true;
- $ret = $this->_tpl->get($block);
- $this->_tpl->clearCache = $oldClear;
- }
- return $ret;
- }
-} // end class HTML_QuickForm_Renderer_ITStatic
-?>
\ No newline at end of file
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * A concrete renderer for HTML_QuickForm, makes an object from form contents
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Ron McClain <ron@humaniq.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * An abstract base class for QuickForm renderers
- */
-require_once 'HTML/QuickForm/Renderer.php';
-
-/**
- * A concrete renderer for HTML_QuickForm, makes an object from form contents
- *
- * Based on HTML_Quickform_Renderer_Array code
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Ron McClain <ron@humaniq.com>
- * @version Release: 3.2.16
- * @since 3.1.1
- */
-class HTML_QuickForm_Renderer_Object extends HTML_QuickForm_Renderer
-{
- /**#@+
- * @access private
- */
- /**
- * The object being generated
- * @var QuickformForm
- */
- var $_obj= null;
-
- /**
- * Number of sections in the form (i.e. number of headers in it)
- * @var integer $_sectionCount
- */
- var $_sectionCount;
-
- /**
- * Current section number
- * @var integer $_currentSection
- */
- var $_currentSection;
-
- /**
- * Object representing current group
- * @var object $_currentGroup
- */
- var $_currentGroup = null;
-
- /**
- * Class of Element Objects
- * @var object $_elementType
- */
- var $_elementType = 'QuickFormElement';
-
- /**
- * Additional style information for different elements
- * @var array $_elementStyles
- */
- var $_elementStyles = array();
-
- /**
- * true: collect all hidden elements into string; false: process them as usual form elements
- * @var bool $_collectHidden
- */
- var $_collectHidden = false;
- /**#@-*/
-
-
- /**
- * Constructor
- *
- * @param bool true: collect all hidden elements
- * @access public
- */
- function HTML_QuickForm_Renderer_Object($collecthidden = false)
- {
- $this->HTML_QuickForm_Renderer();
- $this->_collectHidden = $collecthidden;
- $this->_obj = new QuickformForm;
- }
-
- /**
- * Return the rendered Object
- * @access public
- */
- function toObject()
- {
- return $this->_obj;
- }
-
- /**
- * Set the class of the form elements. Defaults to QuickformElement.
- * @param string Name of element class
- * @access public
- */
- function setElementType($type)
- {
- $this->_elementType = $type;
- }
-
- function startForm(&$form)
- {
- $this->_obj->frozen = $form->isFrozen();
- $this->_obj->javascript = $form->getValidationScript();
- $this->_obj->attributes = $form->getAttributes(true);
- $this->_obj->requirednote = $form->getRequiredNote();
- $this->_obj->errors = new StdClass;
-
- if($this->_collectHidden) {
- $this->_obj->hidden = '';
- }
- $this->_elementIdx = 1;
- $this->_currentSection = null;
- $this->_sectionCount = 0;
- } // end func startForm
-
- function renderHeader(&$header)
- {
- $hobj = new StdClass;
- $hobj->header = $header->toHtml();
- $this->_obj->sections[$this->_sectionCount] = $hobj;
- $this->_currentSection = $this->_sectionCount++;
- }
-
- function renderElement(&$element, $required, $error)
- {
- $elObj = $this->_elementToObject($element, $required, $error);
- if(!empty($error)) {
- $name = $elObj->name;
- $this->_obj->errors->$name = $error;
- }
- $this->_storeObject($elObj);
- } // end func renderElement
-
- function renderHidden(&$element)
- {
- if($this->_collectHidden) {
- $this->_obj->hidden .= $element->toHtml() . "\n";
- } else {
- $this->renderElement($element, false, null);
- }
- } //end func renderHidden
-
- function startGroup(&$group, $required, $error)
- {
- $this->_currentGroup = $this->_elementToObject($group, $required, $error);
- if(!empty($error)) {
- $name = $this->_currentGroup->name;
- $this->_obj->errors->$name = $error;
- }
- } // end func startGroup
-
- function finishGroup(&$group)
- {
- $this->_storeObject($this->_currentGroup);
- $this->_currentGroup = null;
- } // end func finishGroup
-
- /**
- * Creates an object representing an element
- *
- * @access private
- * @param HTML_QuickForm_element form element being rendered
- * @param required bool Whether an element is required
- * @param error string Error associated with the element
- * @return object
- */
- function _elementToObject(&$element, $required, $error)
- {
- if($this->_elementType) {
- $ret = new $this->_elementType;
- }
- $ret->name = $element->getName();
- $ret->value = $element->getValue();
- $ret->type = $element->getType();
- $ret->frozen = $element->isFrozen();
- $labels = $element->getLabel();
- if (is_array($labels)) {
- $ret->label = array_shift($labels);
- foreach ($labels as $key => $label) {
- $key = is_int($key)? $key + 2: $key;
- $ret->{'label_' . $key} = $label;
- }
- } else {
- $ret->label = $labels;
- }
- $ret->required = $required;
- $ret->error = $error;
-
- if(isset($this->_elementStyles[$ret->name])) {
- $ret->style = $this->_elementStyles[$ret->name];
- $ret->styleTemplate = "styles/". $ret->style .".html";
- }
- if($ret->type == 'group') {
- $ret->separator = $element->_separator;
- $ret->elements = array();
- } else {
- $ret->html = $element->toHtml();
- }
- return $ret;
- }
-
- /**
- * Stores an object representation of an element in the form array
- *
- * @access private
- * @param QuickformElement Object representation of an element
- * @return void
- */
- function _storeObject($elObj)
- {
- $name = $elObj->name;
- if(is_object($this->_currentGroup) && $elObj->type != 'group') {
- $this->_currentGroup->elements[] = $elObj;
- } elseif (isset($this->_currentSection)) {
- $this->_obj->sections[$this->_currentSection]->elements[] = $elObj;
- } else {
- $this->_obj->elements[] = $elObj;
- }
- }
-
- function setElementStyle($elementName, $styleName = null)
- {
- if(is_array($elementName)) {
- $this->_elementStyles = array_merge($this->_elementStyles, $elementName);
- } else {
- $this->_elementStyles[$elementName] = $styleName;
- }
- }
-
-} // end class HTML_QuickForm_Renderer_Object
-
-
-
-/**
- * Convenience class for the form object passed to outputObject()
- *
- * Eg.
- * <pre>
- * {form.outputJavaScript():h}
- * {form.outputHeader():h}
- * <table>
- * <tr>
- * <td>{form.name.label:h}</td><td>{form.name.html:h}</td>
- * </tr>
- * </table>
- * </form>
- * </pre>
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Ron McClain <ron@humaniq.com>
- * @version Release: 3.2.16
- * @since 3.1.1
- */
-class QuickformForm
-{
- /**
- * Whether the form has been frozen
- * @var boolean $frozen
- */
- var $frozen;
-
- /**
- * Javascript for client-side validation
- * @var string $javascript
- */
- var $javascript;
-
- /**
- * Attributes for form tag
- * @var string $attributes
- */
- var $attributes;
-
- /**
- * Note about required elements
- * @var string $requirednote
- */
- var $requirednote;
-
- /**
- * Collected html of all hidden variables
- * @var string $hidden
- */
- var $hidden;
-
- /**
- * Set if there were validation errors.
- * StdClass object with element names for keys and their
- * error messages as values
- * @var object $errors
- */
- var $errors;
-
- /**
- * Array of QuickformElementObject elements. If there are headers in the form
- * this will be empty and the elements will be in the
- * separate sections
- * @var array $elements
- */
- var $elements;
-
- /**
- * Array of sections contained in the document
- * @var array $sections
- */
- var $sections;
-
- /**
- * Output <form> header
- * {form.outputHeader():h}
- * @return string <form attributes>
- */
- function outputHeader()
- {
- return "<form " . $this->attributes . ">\n";
- }
-
- /**
- * Output form javascript
- * {form.outputJavaScript():h}
- * @return string Javascript
- */
- function outputJavaScript()
- {
- return $this->javascript;
- }
-} // end class QuickformForm
-
-
-/**
- * Convenience class describing a form element.
- *
- * The properties defined here will be available from
- * your flexy templates by referencing
- * {form.zip.label:h}, {form.zip.html:h}, etc.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Ron McClain <ron@humaniq.com>
- * @version Release: 3.2.16
- * @since 3.1.1
- */
-class QuickformElement
-{
- /**
- * Element name
- * @var string $name
- */
- var $name;
-
- /**
- * Element value
- * @var mixed $value
- */
- var $value;
-
- /**
- * Type of element
- * @var string $type
- */
- var $type;
-
- /**
- * Whether the element is frozen
- * @var boolean $frozen
- */
- var $frozen;
-
- /**
- * Label for the element
- * @var string $label
- */
- var $label;
-
- /**
- * Whether element is required
- * @var boolean $required
- */
- var $required;
-
- /**
- * Error associated with the element
- * @var string $error
- */
- var $error;
-
- /**
- * Some information about element style
- * @var string $style
- */
- var $style;
-
- /**
- * HTML for the element
- * @var string $html
- */
- var $html;
-
- /**
- * If element is a group, the group separator
- * @var mixed $separator
- */
- var $separator;
-
- /**
- * If element is a group, an array of subelements
- * @var array $elements
- */
- var $elements;
-
- function isType($type)
- {
- return ($this->type == $type);
- }
-
- function notFrozen()
- {
- return !$this->frozen;
- }
-
- function isButton()
- {
- return ($this->type == "submit" || $this->type == "reset");
- }
-
-
- /**
- * XXX: why does it use Flexy when all other stuff here does not depend on it?
- */
- function outputStyle()
- {
- ob_start();
- HTML_Template_Flexy::staticQuickTemplate('styles/' . $this->style . '.html', $this);
- $ret = ob_get_contents();
- ob_end_clean();
- return $ret;
- }
-} // end class QuickformElement
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * QuickForm renderer for Flexy template engine, static version.
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Ron McClain <ron@humaniq.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * A concrete renderer for HTML_QuickForm, makes an object from form contents
- */
-require_once 'HTML/QuickForm/Renderer/Object.php';
-
-/**
- * QuickForm renderer for Flexy template engine, static version.
- *
- * A static renderer for HTML_Quickform. Makes a QuickFormFlexyObject
- * from the form content suitable for use with a Flexy template
- *
- * Usage:
- * <code>
- * $form =& new HTML_QuickForm('form', 'POST');
- * $template =& new HTML_Template_Flexy();
- * $renderer =& new HTML_QuickForm_Renderer_ObjectFlexy(&$template);
- * $renderer->setHtmlTemplate("html.html");
- * $renderer->setLabelTemplate("label.html");
- * $form->accept($renderer);
- * $view = new StdClass;
- * $view->form = $renderer->toObject();
- * $template->compile("mytemplate.html");
- * </code>
- *
- * Based on the code for HTML_QuickForm_Renderer_ArraySmarty
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Ron McClain <ron@humaniq.com>
- * @version Release: 3.2.16
- * @since 3.1.1
- */
-class HTML_QuickForm_Renderer_ObjectFlexy extends HTML_QuickForm_Renderer_Object
-{
- /**#@+
- * @access private
- */
- /**
- * HTML_Template_Flexy instance
- * @var object $_flexy
- */
- var $_flexy;
-
- /**
- * Current element index
- * @var integer $_elementIdx
- */
- var $_elementIdx;
-
- /**
- * The current element index inside a group
- * @var integer $_groupElementIdx
- */
- var $_groupElementIdx = 0;
-
- /**
- * Name of template file for form html
- * @var string $_html
- * @see setRequiredTemplate()
- */
- var $_html = '';
-
- /**
- * Name of template file for form labels
- * @var string $label
- * @see setErrorTemplate()
- */
- var $label = '';
-
- /**
- * Class of the element objects, so you can add your own
- * element methods
- * @var string $_elementType
- */
- var $_elementType = 'QuickformFlexyElement';
- /**#@-*/
-
- /**
- * Constructor
- *
- * @param HTML_Template_Flexy template object to use
- * @public
- */
- function HTML_QuickForm_Renderer_ObjectFlexy(&$flexy)
- {
- $this->HTML_QuickForm_Renderer_Object(true);
- $this->_obj = new QuickformFlexyForm();
- $this->_flexy =& $flexy;
- } // end constructor
-
- function renderHeader(&$header)
- {
- if($name = $header->getName()) {
- $this->_obj->header->$name = $header->toHtml();
- } else {
- $this->_obj->header[$this->_sectionCount] = $header->toHtml();
- }
- $this->_currentSection = $this->_sectionCount++;
- } // end func renderHeader
-
- function startGroup(&$group, $required, $error)
- {
- parent::startGroup($group, $required, $error);
- $this->_groupElementIdx = 1;
- } //end func startGroup
-
- /**
- * Creates an object representing an element containing
- * the key for storing this
- *
- * @access private
- * @param HTML_QuickForm_element form element being rendered
- * @param bool Whether an element is required
- * @param string Error associated with the element
- * @return object
- */
- function _elementToObject(&$element, $required, $error)
- {
- $ret = parent::_elementToObject($element, $required, $error);
- if($ret->type == 'group') {
- $ret->html = $element->toHtml();
- unset($ret->elements);
- }
- if(!empty($this->_label)) {
- $this->_renderLabel($ret);
- }
-
- if(!empty($this->_html)) {
- $this->_renderHtml($ret);
- $ret->error = $error;
- }
-
- // Create an element key from the name
- if (false !== ($pos = strpos($ret->name, '[')) || is_object($this->_currentGroup)) {
- if (!$pos) {
- $keys = '->{\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $ret->name) . '\'}';
- } else {
- $keys = '->{\'' . str_replace(
- array('\\', '\'', '[', ']'), array('\\\\', '\\\'', '\'}->{\'', ''),
- $ret->name
- ) . '\'}';
- }
- // special handling for elements in native groups
- if (is_object($this->_currentGroup)) {
- // skip unnamed group items unless radios: no name -> no static access
- // identification: have the same key string as the parent group
- if ($this->_currentGroup->keys == $keys && 'radio' != $ret->type) {
- return false;
- }
- // reduce string of keys by remove leading group keys
- if (0 === strpos($keys, $this->_currentGroup->keys)) {
- $keys = substr_replace($keys, '', 0, strlen($this->_currentGroup->keys));
- }
- }
- } elseif (0 == strlen($ret->name)) {
- $keys = '->{\'element_' . $this->_elementIdx . '\'}';
- } else {
- $keys = '->{\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $ret->name) . '\'}';
- }
- // for radios: add extra key from value
- if ('radio' == $ret->type && '[]' != substr($keys, -2)) {
- $keys .= '->{\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $ret->value) . '\'}';
- }
- $ret->keys = $keys;
- $this->_elementIdx++;
- return $ret;
- }
-
- /**
- * Stores an object representation of an element in the
- * QuickformFormObject instance
- *
- * @access private
- * @param QuickformElement Object representation of an element
- * @return void
- */
- function _storeObject($elObj)
- {
- if ($elObj) {
- $keys = $elObj->keys;
- unset($elObj->keys);
- if(is_object($this->_currentGroup) && ('group' != $elObj->type)) {
- $code = '$this->_currentGroup' . $keys . ' = $elObj;';
- } else {
- $code = '$this->_obj' . $keys . ' = $elObj;';
- }
- eval($code);
- }
- }
-
- /**
- * Set the filename of the template to render html elements.
- * In your template, {html} is replaced by the unmodified html.
- * If the element is required, {required} will be true.
- * Eg.
- * <pre>
- * {if:error}
- * <font color="red" size="1">{error:h}</font><br />
- * {end:}
- * {html:h}
- * </pre>
- *
- * @access public
- * @param string Filename of template
- * @return void
- */
- function setHtmlTemplate($template)
- {
- $this->_html = $template;
- }
-
- /**
- * Set the filename of the template to render form labels
- * In your template, {label} is replaced by the unmodified label.
- * {error} will be set to the error, if any. {required} will
- * be true if this is a required field
- * Eg.
- * <pre>
- * {if:required}
- * <font color="orange" size="1">*</font>
- * {end:}
- * {label:h}
- * </pre>
- *
- * @access public
- * @param string Filename of template
- * @return void
- */
- function setLabelTemplate($template)
- {
- $this->_label = $template;
- }
-
- function _renderLabel(&$ret)
- {
- $this->_flexy->compile($this->_label);
- $ret->label = $this->_flexy->bufferedOutputObject($ret);
- }
-
- function _renderHtml(&$ret)
- {
- $this->_flexy->compile($this->_html);
- $ret->html = $this->_flexy->bufferedOutputObject($ret);
- }
-} // end class HTML_QuickForm_Renderer_ObjectFlexy
-
-/**
- * Adds nothing to QuickformForm, left for backwards compatibility
- *
- * @category HTML
- * @package HTML_QuickForm
- * @ignore
- */
-class QuickformFlexyForm extends QuickformForm
-{
-}
-
-/**
- * Adds nothing to QuickformElement, left for backwards compatibility
- *
- * @category HTML
- * @package HTML_QuickForm
- * @ignore
- */
-class QuickformFlexyElement extends QuickformElement
-{
-}
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * A renderer that makes it quick and easy to create customized forms.
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Jason Rust <jrust@rustyparts.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * A concrete renderer for HTML_QuickForm, based on QuickForm 2.x built-in one
- */
-require_once 'HTML/QuickForm/Renderer/Default.php';
-
-/**
- * A renderer that makes it quick and easy to create customized forms.
- *
- * This renderer has three main distinctives: an easy way to create
- * custom-looking forms, the ability to separate the creation of form
- * elements from their display, and being able to use QuickForm in
- * widget-based template systems. See the online docs for more info.
- * For a usage example see: docs/renderers/QuickHtml_example.php
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Jason Rust <jrust@rustyparts.com>
- * @version Release: 3.2.16
- * @since 3.1.1
- */
-class HTML_QuickForm_Renderer_QuickHtml extends HTML_QuickForm_Renderer_Default {
- // {{{ properties
-
- /**
- * The array of rendered elements
- * @var array
- */
- var $renderedElements = array();
-
- // }}}
- // {{{ constructor
-
- /**
- * Constructor
- *
- * @access public
- * @return void
- */
- function HTML_QuickForm_Renderer_QuickHtml()
- {
- $this->HTML_QuickForm_Renderer_Default();
- // The default templates aren't used for this renderer
- $this->clearAllTemplates();
- } // end constructor
-
- // }}}
- // {{{ toHtml()
-
- /**
- * returns the HTML generated for the form
- *
- * @param string $data (optional) Any extra data to put before the end of the form
- *
- * @access public
- * @return string
- */
- function toHtml($data = '')
- {
- // Render any elements that haven't been rendered explicitly by elementToHtml()
- foreach (array_keys($this->renderedElements) as $key) {
- if (!$this->renderedElements[$key]['rendered']) {
- $this->renderedElements[$key]['rendered'] = true;
- $data .= $this->renderedElements[$key]['html'] . "\n";
- }
- }
-
- // Insert the extra data and form elements at the end of the form
- $this->_html = str_replace('</form>', $data . "\n</form>", $this->_html);
- return $this->_html;
- } // end func toHtml
-
- // }}}
- // {{{ elementToHtml()
-
- /**
- * Gets the html for an element and marks it as rendered.
- *
- * @param string $elementName The element name
- * @param string $elementValue (optional) The value of the element. This is only useful
- * for elements that have the same name (i.e. radio and checkbox), but
- * different values
- *
- * @access public
- * @return string The html for the QuickForm element
- * @throws HTML_QuickForm_Error
- */
- function elementToHtml($elementName, $elementValue = null)
- {
- $elementKey = null;
- // Find the key for the element
- foreach ($this->renderedElements as $key => $data) {
- if ($data['name'] == $elementName &&
- // See if the value must match as well
- (is_null($elementValue) ||
- $data['value'] == $elementValue)) {
- $elementKey = $key;
- break;
- }
- }
-
- if (is_null($elementKey)) {
- $msg = is_null($elementValue) ? "Element $elementName does not exist." :
- "Element $elementName with value of $elementValue does not exist.";
- return PEAR::raiseError(null, QUICKFORM_UNREGISTERED_ELEMENT, null, E_USER_WARNING, $msg, 'HTML_QuickForm_Error', true);
- } else {
- if ($this->renderedElements[$elementKey]['rendered']) {
- $msg = is_null($elementValue) ? "Element $elementName has already been rendered." :
- "Element $elementName with value of $elementValue has already been rendered.";
- return PEAR::raiseError(null, QUICKFORM_ERROR, null, E_USER_WARNING, $msg, 'HTML_QuickForm_Error', true);
- } else {
- $this->renderedElements[$elementKey]['rendered'] = true;
- return $this->renderedElements[$elementKey]['html'];
- }
- }
- } // end func elementToHtml
-
- // }}}
- // {{{ renderElement()
-
- /**
- * Gets the html for an element and adds it to the array by calling
- * parent::renderElement()
- *
- * @param HTML_QuickForm_element form element being visited
- * @param bool Whether an element is required
- * @param string An error message associated with an element
- *
- * @access public
- * @return mixed HTML string of element if $immediateRender is set, else we just add the
- * html to the global _html string
- */
- function renderElement(&$element, $required, $error)
- {
- $this->_html = '';
- parent::renderElement($element, $required, $error);
- if (!$this->_inGroup) {
- $this->renderedElements[] = array(
- 'name' => $element->getName(),
- 'value' => $element->getValue(),
- 'html' => $this->_html,
- 'rendered' => false);
- }
- $this->_html = '';
- } // end func renderElement
-
- // }}}
- // {{{ renderHidden()
-
- /**
- * Gets the html for a hidden element and adds it to the array.
- *
- * @param HTML_QuickForm_element hidden form element being visited
- * @access public
- * @return void
- */
- function renderHidden(&$element)
- {
- $this->renderedElements[] = array(
- 'name' => $element->getName(),
- 'value' => $element->getValue(),
- 'html' => $element->toHtml(),
- 'rendered' => false);
- } // end func renderHidden
-
- // }}}
- // {{{ finishGroup()
-
- /**
- * Gets the html for the group element and adds it to the array by calling
- * parent::finishGroup()
- *
- * @param HTML_QuickForm_group group being visited
- * @access public
- * @return void
- */
- function finishGroup(&$group)
- {
- $this->_html = '';
- parent::finishGroup($group);
- $this->renderedElements[] = array(
- 'name' => $group->getName(),
- 'value' => $group->getValue(),
- 'html' => $this->_html,
- 'rendered' => false);
- $this->_html = '';
- } // end func finishGroup
-
- // }}}
-} // end class HTML_QuickForm_Renderer_QuickHtml
-?>
+++ /dev/null
-<?php
-/**
- * Replacement for the default renderer of HTML_QuickForm that uses only XHTML
- * and CSS but no table tags, and generates fully valid XHTML output
- *
- * PHP versions 4 and 5
- *
- * LICENSE:
- *
- * Copyright (c) 2005-2007, Mark Wiesemann <wiesemann@php.net>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * The names of the authors may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * @category HTML
- * @package HTML_QuickForm_Renderer_Tableless
- * @author Alexey Borzov <borz_off@cs.msu.su>
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Mark Wiesemann <wiesemann@php.net>
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Tableless.php 271939 2008-12-26 20:22:30Z wiesemann $
- * @link http://pear.php.net/package/HTML_QuickForm_Renderer_Tableless
- */
-
-require_once 'HTML/QuickForm/Renderer/Default.php';
-
-/**
- * Replacement for the default renderer of HTML_QuickForm that uses only XHTML
- * and CSS but no table tags, and generates fully valid XHTML output
- *
- * You need to specify a stylesheet like the one that you find in
- * data/stylesheet.css to make this work.
- *
- * @category HTML
- * @package HTML_QuickForm_Renderer_Tableless
- * @author Alexey Borzov <borz_off@cs.msu.su>
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Mark Wiesemann <wiesemann@php.net>
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 0.6.2
- * @link http://pear.php.net/package/HTML_QuickForm_Renderer_Tableless
- */
-class HTML_QuickForm_Renderer_Tableless extends HTML_QuickForm_Renderer_Default
-{
- /**
- * Header Template string
- * @var string
- * @access private
- */
- var $_headerTemplate = "\n\t\t<legend>{header}</legend>\n\t\t<ol>";
-
- /**
- * Element template string
- * @var string
- * @access private
- */
- var $_elementTemplate =
- "\n\t\t\t<li><label class=\"element\"><!-- BEGIN required --><span class=\"required\">*</span><!-- END required -->{label}</label><div class=\"element<!-- BEGIN error --> error<!-- END error -->\"><!-- BEGIN error --><span class=\"error\">{error}</span><br /><!-- END error -->{element}</div></li>";
-
- /**
- * Form template string
- * @var string
- * @access private
- */
- var $_formTemplate =
- "\n<form{attributes}>\n\t<div style=\"display: none;\">\n{hidden}\t</div>\n{content}\n</form>";
-
- /**
- * Template used when opening a fieldset
- * @var string
- * @access private
- */
- var $_openFieldsetTemplate = "\n\t<fieldset{id}{attributes}>";
-
- /**
- * Template used when opening a hidden fieldset
- * (i.e. a fieldset that is opened when there is no header element)
- * @var string
- * @access private
- */
- var $_openHiddenFieldsetTemplate = "\n\t<fieldset class=\"hidden{class}\">\n\t\t<ol>";
-
- /**
- * Template used when closing a fieldset
- * @var string
- * @access private
- */
- var $_closeFieldsetTemplate = "\n\t\t</ol>\n\t</fieldset>";
-
- /**
- * Required Note template string
- * @var string
- * @access private
- */
- var $_requiredNoteTemplate =
- "\n\t\t\t<li class=\"reqnote\"><label class=\"element\"> </label>{requiredNote}</li>";
-
- /**
- * How many fieldsets are open
- * @var integer
- * @access private
- */
- var $_fieldsetsOpen = 0;
-
- /**
- * Array of element names that indicate the end of a fieldset
- * (a new one will be opened when the next header element occurs)
- * @var array
- * @access private
- */
- var $_stopFieldsetElements = array();
-
- /**
- * Name of the currently active group
- * @var string
- * @access private
- */
- var $_currentGroupName = '';
-
- /**
- * Constructor
- *
- * @access public
- */
- function HTML_QuickForm_Renderer_Tableless()
- {
- $this->HTML_QuickForm_Renderer_Default();
- } // end constructor
-
- /**
- * Called when visiting a header element
- *
- * @param object An HTML_QuickForm_header element being visited
- * @access public
- * @return void
- */
- function renderHeader(&$header)
- {
- $name = $header->getName();
- $id = empty($name) ? '' : ' id="' . $name . '"';
- if (!empty($name) && isset($this->_templates[$name])) {
- $header_html = str_replace('{header}', $header->toHtml(), $this->_templates[$name]);
- } else {
- $header_html = str_replace('{header}', $header->toHtml(), $this->_headerTemplate);
- }
- $attributes = $header->getAttributes();
- $strAttr = '';
- if (is_array($attributes)) {
- $charset = HTML_Common::charset();
- foreach ($attributes as $key => $value) {
- if ($key == 'name') {
- continue;
- }
- $strAttr .= ' ' . $key . '="' . htmlspecialchars($value, ENT_COMPAT, $charset) . '"';
- }
- }
- if ($this->_fieldsetsOpen > 0) {
- $this->_html .= $this->_closeFieldsetTemplate;
- $this->_fieldsetsOpen--;
- }
- $openFieldsetTemplate = str_replace('{id}', $id, $this->_openFieldsetTemplate);
- $openFieldsetTemplate = str_replace('{attributes}',
- $strAttr,
- $openFieldsetTemplate);
- $this->_html .= $openFieldsetTemplate . $header_html;
- $this->_fieldsetsOpen++;
- } // end func renderHeader
-
- /**
- * Renders an element Html
- * Called when visiting an element
- *
- * @param object An HTML_QuickForm_element object being visited
- * @param bool Whether an element is required
- * @param string An error message associated with an element
- * @access public
- * @return void
- */
- function renderElement(&$element, $required, $error)
- {
- $this->_handleStopFieldsetElements($element->getName());
- if (!$this->_inGroup) {
- $html = $this->_prepareTemplate($element->getName(), $element->getLabel(), $required, $error);
- // the following lines (until the "elseif") were changed / added
- // compared to the default renderer
- $element_html = $element->toHtml();
- if (!is_null($element->getAttribute('id'))) {
- $id = $element->getAttribute('id');
- } else {
- $id = $element->getName();
- }
- if ($element->getType() != 'static' && !empty($id)) {
- $html = str_replace('<label', '<label for="' . $id . '"', $html);
- $element_html = preg_replace(preg_quote('#name="' . $id . '#'),
- 'id="' . $id . '" name="' . $id,
- $element_html,
- 1);
- }
- $this->_html .= str_replace('{element}', $element_html, $html);
- } elseif (!empty($this->_groupElementTemplate)) {
- $html = str_replace('{label}', $element->getLabel(), $this->_groupElementTemplate);
- if ($required) {
- $html = str_replace('<!-- BEGIN required -->', '', $html);
- $html = str_replace('<!-- END required -->', '', $html);
- } else {
- $html = preg_replace("/([ \t\n\r]*)?<!-- BEGIN required -->(\s|\S)*<!-- END required -->([ \t\n\r]*)?/i", '', $html);
- }
- $this->_groupElements[] = str_replace('{element}', $element->toHtml(), $html);
-
- } else {
- $element_html = $element->toHtml();
- // add "id" attribute to first element of the group
- if (count($this->_groupElements) === 0) {
- if (!is_null($element->getAttribute('id'))) {
- $id = $element->getAttribute('id');
- } else {
- $id = $element->getName();
- }
- $groupId = $this->_currentGroupName;
- if ($element->getType() != 'static' && !empty($id)) {
- $element_html = preg_replace(preg_quote('#name="' . $id . '#'),
- 'id="' . $groupId . '" name="' . $id,
- $element_html,
- 1);
- }
- }
- $this->_groupElements[] = $element_html;
- }
- } // end func renderElement
-
- /**
- * Renders an hidden element
- * Called when visiting a hidden element
- *
- * @param object An HTML_QuickForm_hidden object being visited
- * @access public
- * @return void
- */
- function renderHidden(&$element)
- {
- if (!is_null($element->getAttribute('id'))) {
- $id = $element->getAttribute('id');
- } else {
- $id = $element->getName();
- }
- $html = $element->toHtml();
- if (!empty($id)) {
- $html = str_replace('name="' . $id,
- 'id="' . $id . '" name="' . $id,
- $html);
- }
- $this->_hiddenHtml .= $html . "\n";
- } // end func renderHidden
-
- /**
- * Called when visiting a group, before processing any group elements
- *
- * @param object An HTML_QuickForm_group object being visited
- * @param bool Whether a group is required
- * @param string An error message associated with a group
- * @access public
- * @return void
- */
- function startGroup(&$group, $required, $error)
- {
- $this->_handleStopFieldsetElements($group->getName());
- $name = $group->getName();
- $this->_groupTemplate = $this->_prepareTemplate($name, $group->getLabel(), $required, $error);
- $this->_groupTemplate = str_replace('<label', '<label for="' . $name . '"', $this->_groupTemplate);
- $this->_groupElementTemplate = empty($this->_groupTemplates[$name])? '': $this->_groupTemplates[$name];
- $this->_groupWrap = empty($this->_groupWraps[$name])? '': $this->_groupWraps[$name];
- $this->_groupElements = array();
- $this->_inGroup = true;
- $this->_currentGroupName = $name;
- } // end func startGroup
-
- /**
- * Called when visiting a group, after processing all group elements
- *
- * @param object An HTML_QuickForm_group object being visited
- * @access public
- * @return void
- */
- function finishGroup(&$group)
- {
- $separator = $group->_separator;
- if (is_array($separator)) {
- $count = count($separator);
- $html = '';
- for ($i = 0; $i < count($this->_groupElements); $i++) {
- $html .= (0 == $i? '': $separator[($i - 1) % $count]) . $this->_groupElements[$i];
- }
- } else {
- if (is_null($separator)) {
- $separator = ' ';
- }
- $html = implode((string)$separator, $this->_groupElements);
- }
- if (!empty($this->_groupWrap)) {
- $html = str_replace('{content}', $html, $this->_groupWrap);
- }
- if (!is_null($group->getAttribute('id'))) {
- $id = $group->getAttribute('id');
- } else {
- $id = $group->getName();
- }
- $groupTemplate = $this->_groupTemplate;
-
- $this->_html .= str_replace('{element}', $html, $groupTemplate);
- $this->_inGroup = false;
- } // end func finishGroup
-
- /**
- * Called when visiting a form, before processing any form elements
- *
- * @param object An HTML_QuickForm object being visited
- * @access public
- * @return void
- */
- function startForm(&$form)
- {
- $this->_fieldsetsOpen = 0;
- parent::startForm($form);
- } // end func startForm
-
- /**
- * Called when visiting a form, after processing all form elements
- * Adds required note, form attributes, validation javascript and form content.
- *
- * @param object An HTML_QuickForm object being visited
- * @access public
- * @return void
- */
- function finishForm(&$form)
- {
- // add a required note, if one is needed
- if (!empty($form->_required) && !$form->_freezeAll) {
- $requiredNote = $form->getRequiredNote();
- // replace default required note by DOM/XHTML optimized note
- if ($requiredNote == '<span style="font-size:80%; color:#ff0000;">*</span><span style="font-size:80%;"> denotes required field</span>') {
- $requiredNote = '<span class="required">*</span> denotes required field';
- }
- $this->_html .= str_replace('{requiredNote}', $requiredNote, $this->_requiredNoteTemplate);
- }
- // close the open fieldset
- if ($this->_fieldsetsOpen > 0) {
- $this->_html .= $this->_closeFieldsetTemplate;
- $this->_fieldsetsOpen--;
- }
- // add form attributes and content
- $html = str_replace('{attributes}', $form->getAttributes(true), $this->_formTemplate);
- if (strpos($this->_formTemplate, '{hidden}')) {
- $html = str_replace('{hidden}', $this->_hiddenHtml, $html);
- } else {
- $this->_html .= $this->_hiddenHtml;
- }
- $this->_hiddenHtml = '';
- $this->_html = str_replace('{content}', $this->_html, $html);
- $this->_html = str_replace('></label>', '> </label>', $this->_html);
- // add a validation script
- if ('' != ($script = $form->getValidationScript())) {
- $this->_html = $script . "\n" . $this->_html;
- }
- } // end func finishForm
-
- /**
- * Sets the template used when opening a fieldset
- *
- * @param string The HTML used when opening a fieldset
- * @access public
- * @return void
- */
- function setOpenFieldsetTemplate($html)
- {
- $this->_openFieldsetTemplate = $html;
- } // end func setOpenFieldsetTemplate
-
- /**
- * Sets the template used when opening a hidden fieldset
- * (i.e. a fieldset that is opened when there is no header element)
- *
- * @param string The HTML used when opening a hidden fieldset
- * @access public
- * @return void
- */
- function setOpenHiddenFieldsetTemplate($html)
- {
- $this->_openHiddenFieldsetTemplate = $html;
- } // end func setOpenHiddenFieldsetTemplate
-
- /**
- * Sets the template used when closing a fieldset
- *
- * @param string The HTML used when closing a fieldset
- * @access public
- * @return void
- */
- function setCloseFieldsetTemplate($html)
- {
- $this->_closeFieldsetTemplate = $html;
- } // end func setCloseFieldsetTemplate
-
- /**
- * Adds one or more element names that indicate the end of a fieldset
- * (a new one will be opened when a the next header element occurs)
- *
- * @param mixed Element name(s) (as array or string)
- * @param string (optional) Class name for the fieldset(s)
- * @access public
- * @return void
- */
- function addStopFieldsetElements($element, $class = '')
- {
- if (is_array($element)) {
- $elements = array();
- foreach ($element as $name) {
- $elements[$name] = $class;
- }
- $this->_stopFieldsetElements = array_merge($this->_stopFieldsetElements,
- $elements);
- } else {
- $this->_stopFieldsetElements[$element] = $class;
- }
- } // end func addStopFieldsetElements
-
- /**
- * Handle element/group names that indicate the end of a group
- *
- * @param string The name of the element or group
- * @access private
- * @return void
- */
- function _handleStopFieldsetElements($element)
- {
- // if the element/group name indicates the end of a fieldset, close
- // the fieldset
- if ( array_key_exists($element, $this->_stopFieldsetElements)
- && $this->_fieldsetsOpen > 0
- ) {
- $this->_html .= $this->_closeFieldsetTemplate;
- $this->_fieldsetsOpen--;
- }
- // if no fieldset was opened, we need to open a hidden one here to get
- // XHTML validity
- if ($this->_fieldsetsOpen === 0) {
- $replace = '';
- if ( array_key_exists($element, $this->_stopFieldsetElements)
- && $this->_stopFieldsetElements[$element] != ''
- ) {
- $replace = ' ' . $this->_stopFieldsetElements[$element];
- }
- $this->_html .= str_replace('{class}', $replace,
- $this->_openHiddenFieldsetTemplate);
- $this->_fieldsetsOpen++;
- }
- } // end func _handleStopFieldsetElements
-
- /**
- * Sets element template
- *
- * @param string The HTML surrounding an element
- * @param mixed (optional) Name(s) of the element to apply template
- * for (either single element name as string or multiple
- * element names as an array)
- * @access public
- * @return void
- */
- function setElementTemplate($html, $element = null)
- {
- if (is_null($element)) {
- $this->_elementTemplate = $html;
- } elseif (is_array($element)) {
- foreach ($element as $name) {
- $this->_templates[$name] = $html;
- }
- } else {
- $this->_templates[$element] = $html;
- }
- } // end func setElementTemplate
-
-} // end class HTML_QuickForm_Renderer_Default
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Abstract base class for QuickForm validation rules
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Abstract base class for QuickForm validation rules
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @version Release: 3.2.16
- * @since 3.2
- * @abstract
- */
-class HTML_QuickForm_Rule
-{
- /**
- * Name of the rule to use in validate method
- *
- * This property is used in more global rules like Callback and Regex
- * to determine which callback and which regex is to be used for validation
- *
- * @var string
- * @access public
- */
- var $name;
-
- /**
- * Validates a value
- *
- * @access public
- * @abstract
- */
- function validate($value)
- {
- return true;
- }
-
- /**
- * Sets the rule name
- *
- * @param string rule name
- * @access public
- */
- function setName($ruleName)
- {
- $this->name = $ruleName;
- }
-
- /**
- * Returns the javascript test (the test should return true if the value is INVALID)
- *
- * @param mixed Options for the rule
- * @access public
- * @return array first element is code to setup validation, second is the check itself
- * @abstract
- */
- function getValidationScript($options = null)
- {
- return array('', '');
- }
-}
-?>
\ No newline at end of file
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Validates values using callback functions or methods
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Abstract base class for QuickForm validation rules
- */
-require_once 'HTML/QuickForm/Rule.php';
-
-/**
- * Validates values using callback functions or methods
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @version Release: 3.2.16
- * @since 3.2
- */
-class HTML_QuickForm_Rule_Callback extends HTML_QuickForm_Rule
-{
- /**
- * Array of callbacks
- *
- * Array is in the format:
- * $_data['rulename'] = array('functionname', 'classname');
- * If the callback is not a method, then the class name is not set.
- *
- * @var array
- * @access private
- */
- var $_data = array();
-
- /**
- * Whether to use BC mode for specific rules
- *
- * Previous versions of QF passed element's name as a first parameter
- * to validation functions, but not to validation methods. This behaviour
- * is emulated if you are using 'function' as rule type when registering.
- *
- * @var array
- * @access private
- */
- var $_BCMode = array();
-
- /**
- * Validates a value using a callback
- *
- * @param string $value Value to be checked
- * @param mixed $options Options for callback
- * @access public
- * @return boolean true if value is valid
- */
- function validate($value, $options = null)
- {
- if (isset($this->_data[$this->name])) {
- $callback = $this->_data[$this->name];
- if (isset($callback[1])) {
- return call_user_func(array($callback[1], $callback[0]), $value, $options);
- } elseif ($this->_BCMode[$this->name]) {
- return $callback[0]('', $value, $options);
- } else {
- return $callback[0]($value, $options);
- }
- } elseif (is_callable($options)) {
- return call_user_func($options, $value);
- } else {
- return true;
- }
- } // end func validate
-
- /**
- * Adds new callbacks to the callbacks list
- *
- * @param string $name Name of rule
- * @param string $callback Name of function or method
- * @param string $class Name of class containing the method
- * @param bool $BCMode Backwards compatibility mode
- * @access public
- */
- function addData($name, $callback, $class = null, $BCMode = false)
- {
- if (!empty($class)) {
- $this->_data[$name] = array($callback, $class);
- } else {
- $this->_data[$name] = array($callback);
- }
- $this->_BCMode[$name] = $BCMode;
- } // end func addData
-
-
- function getValidationScript($options = null)
- {
- if (isset($this->_data[$this->name])) {
- $callback = $this->_data[$this->name][0];
- $params = ($this->_BCMode[$this->name]? "'', {jsVar}": '{jsVar}') .
- (isset($options)? ", '{$options}'": '');
- } else {
- $callback = is_array($options)? $options[1]: $options;
- $params = '{jsVar}';
- }
- return array('', "{jsVar} != '' && !{$callback}({$params})");
- } // end func getValidationScript
-
-} // end class HTML_QuickForm_Rule_Callback
-?>
\ No newline at end of file
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Rule to compare two form fields
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Alexey Borzov <avb@php.net>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Abstract base class for QuickForm validation rules
- */
-require_once 'HTML/QuickForm/Rule.php';
-
-/**
- * Rule to compare two form fields
- *
- * The most common usage for this is to ensure that the password
- * confirmation field matches the password field
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Alexey Borzov <avb@php.net>
- * @version Release: 3.2.16
- * @since 3.2
- */
-class HTML_QuickForm_Rule_Compare extends HTML_QuickForm_Rule
-{
- /**
- * Possible operators to use
- * @var array
- * @access private
- */
- var $_operators = array(
- 'eq' => '===',
- 'neq' => '!==',
- 'gt' => '>',
- 'gte' => '>=',
- 'lt' => '<',
- 'lte' => '<=',
- '==' => '===',
- '!=' => '!=='
- );
-
-
- /**
- * Returns the operator to use for comparing the values
- *
- * @access private
- * @param string operator name
- * @return string operator to use for validation
- */
- function _findOperator($name)
- {
- if (empty($name)) {
- return '===';
- } elseif (isset($this->_operators[$name])) {
- return $this->_operators[$name];
- } elseif (in_array($name, $this->_operators)) {
- return $name;
- } else {
- return '===';
- }
- }
-
-
- function validate($values, $operator = null)
- {
- $operator = $this->_findOperator($operator);
- if ('===' != $operator && '!==' != $operator) {
- $compareFn = create_function('$a, $b', 'return floatval($a) ' . $operator . ' floatval($b);');
- } else {
- $compareFn = create_function('$a, $b', 'return strval($a) ' . $operator . ' strval($b);');
- }
-
- return $compareFn($values[0], $values[1]);
- }
-
-
- function getValidationScript($operator = null)
- {
- $operator = $this->_findOperator($operator);
- if ('===' != $operator && '!==' != $operator) {
- $check = "!(Number({jsVar}[0]) {$operator} Number({jsVar}[1]))";
- } else {
- $check = "!(String({jsVar}[0]) {$operator} String({jsVar}[1]))";
- }
- return array('', "'' != {jsVar}[0] && {$check}");
- }
-}
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Email validation rule
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Abstract base class for QuickForm validation rules
- */
-require_once 'HTML/QuickForm/Rule.php';
-
-/**
- * Email validation rule
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @version Release: 3.2.16
- * @since 3.2
- */
-class HTML_QuickForm_Rule_Email extends HTML_QuickForm_Rule
-{
- var $regex = '/^((\"[^\"\f\n\r\t\v\b]+\")|([\w\!\#\$\%\&\'\*\+\-\~\/\^\`\|\{\}]+(\.[\w\!\#\$\%\&\'\*\+\-\~\/\^\`\|\{\}]+)*))@((\[(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))\])|(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))|((([A-Za-z0-9\-])+\.)+[A-Za-z\-]+))$/';
-
- /**
- * Validates an email address
- *
- * @param string $email Email address
- * @param boolean $checkDomain True if dns check should be performed
- * @access public
- * @return boolean true if email is valid
- */
- function validate($email, $checkDomain = false)
- {
- // Fix for bug #10799: add 'D' modifier to regex
- if (preg_match($this->regex . 'D', $email)) {
- if ($checkDomain && function_exists('checkdnsrr')) {
- $tokens = explode('@', $email);
- if (checkdnsrr($tokens[1], 'MX') || checkdnsrr($tokens[1], 'A')) {
- return true;
- }
- return false;
- }
- return true;
- }
- return false;
- } // end func validate
-
-
- function getValidationScript($options = null)
- {
- return array(" var regex = " . $this->regex . ";\n", "{jsVar} != '' && !regex.test({jsVar})");
- } // end func getValidationScript
-
-} // end class HTML_QuickForm_Rule_Email
-?>
\ No newline at end of file
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Checks that the length of value is within range
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Abstract base class for QuickForm validation rules
- */
-require_once 'HTML/QuickForm/Rule.php';
-
-/**
- * Checks that the length of value is within range
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @version Release: 3.2.16
- * @since 3.2
- */
-class HTML_QuickForm_Rule_Range extends HTML_QuickForm_Rule
-{
- /**
- * Validates a value using a range comparison
- *
- * @param string $value Value to be checked
- * @param mixed $options Int for length, array for range
- * @access public
- * @return boolean true if value is valid
- */
- function validate($value, $options = null)
- {
- $length = strlen($value);
- switch ($this->name) {
- case 'minlength': return ($length >= $options);
- case 'maxlength': return ($length <= $options);
- default: return ($length >= $options[0] && $length <= $options[1]);
- }
- } // end func validate
-
-
- function getValidationScript($options = null)
- {
- switch ($this->name) {
- case 'minlength':
- $test = '{jsVar}.length < '.$options;
- break;
- case 'maxlength':
- $test = '{jsVar}.length > '.$options;
- break;
- default:
- $test = '({jsVar}.length < '.$options[0].' || {jsVar}.length > '.$options[1].')';
- }
- return array('', "{jsVar} != '' && {$test}");
- } // end func getValidationScript
-
-} // end class HTML_QuickForm_Rule_Range
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Validates values using regular expressions
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Abstract base class for QuickForm validation rules
- */
-require_once 'HTML/QuickForm/Rule.php';
-
-/**
- * Validates values using regular expressions
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @version Release: 3.2.16
- * @since 3.2
- */
-class HTML_QuickForm_Rule_Regex extends HTML_QuickForm_Rule
-{
- /**
- * Array of regular expressions
- *
- * Array is in the format:
- * $_data['rulename'] = 'pattern';
- *
- * @var array
- * @access private
- */
- var $_data = array(
- 'lettersonly' => '/^[a-zA-Z]+$/',
- 'alphanumeric' => '/^[a-zA-Z0-9]+$/',
- 'numeric' => '/(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)/',
- 'nopunctuation' => '/^[^().\/\*\^\?#!@$%+=,\"\'><~\[\]{}]+$/',
- 'nonzero' => '/^-?[1-9][0-9]*/'
- );
-
- /**
- * Validates a value using a regular expression
- *
- * @param string $value Value to be checked
- * @param string $regex Regular expression
- * @access public
- * @return boolean true if value is valid
- */
- function validate($value, $regex = null)
- {
- // Fix for bug #10799: add 'D' modifier to regex
- if (isset($this->_data[$this->name])) {
- if (!preg_match($this->_data[$this->name] . 'D', $value)) {
- return false;
- }
- } else {
- if (!preg_match($regex . 'D', $value)) {
- return false;
- }
- }
- return true;
- } // end func validate
-
- /**
- * Adds new regular expressions to the list
- *
- * @param string $name Name of rule
- * @param string $pattern Regular expression pattern
- * @access public
- */
- function addData($name, $pattern)
- {
- $this->_data[$name] = $pattern;
- } // end func addData
-
-
- function getValidationScript($options = null)
- {
- $regex = isset($this->_data[$this->name]) ? $this->_data[$this->name] : $options;
-
- // bug #12376, converting unicode escapes and stripping 'u' modifier
- if ($pos = strpos($regex, 'u', strrpos($regex, '/'))) {
- $regex = substr($regex, 0, $pos) . substr($regex, $pos + 1);
- $regex = preg_replace('/(?<!\\\\)(?>\\\\\\\\)*\\\\x{([a-fA-F0-9]+)}/', '\\u$1', $regex);
- }
-
- return array(" var regex = " . $regex . ";\n", "{jsVar} != '' && !regex.test({jsVar})");
- } // end func getValidationScript
-
-} // end class HTML_QuickForm_Rule_Regex
-?>
\ No newline at end of file
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Required elements validation
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Abstract base class for QuickForm validation rules
- */
-require_once 'HTML/QuickForm/Rule.php';
-
-/**
- * Required elements validation
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @version Release: 3.2.16
- * @since 3.2
- */
-class HTML_QuickForm_Rule_Required extends HTML_QuickForm_Rule
-{
- /**
- * Checks if an element is empty
- *
- * @param string $value Value to check
- * @param mixed $options Not used yet
- * @access public
- * @return boolean true if value is not empty
- */
- function validate($value, $options = null)
- {
- if (is_array($value)) {
- return (bool) $value;
- } else if ((string)$value == '') {
- return false;
- }
- return true;
- } // end func validate
-
-
- function getValidationScript($options = null)
- {
- return array('', "{jsVar} == ''");
- } // end func getValidationScript
-
-} // end class HTML_QuickForm_Rule_Required
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Registers rule objects and uses them for validation
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Alexey Borzov <avb@php.net>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Registers rule objects and uses them for validation
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Alexey Borzov <avb@php.net>
- * @version Release: 3.2.16
- * @since 3.2
- */
-class HTML_QuickForm_RuleRegistry
-{
- /**
- * Array containing references to used rules
- * @var array
- * @access private
- */
- var $_rules = array();
-
-
- /**
- * Returns a singleton of HTML_QuickForm_RuleRegistry
- *
- * Usually, only one RuleRegistry object is needed, this is the reason
- * why it is recommended to use this method to get the validation object.
- *
- * @access public
- * @static
- * @return HTML_QuickForm_RuleRegistry
- */
- function &singleton()
- {
- static $obj;
- if (!isset($obj)) {
- $obj = new HTML_QuickForm_RuleRegistry();
- }
- return $obj;
- } // end func singleton
-
- /**
- * Registers a new validation rule
- *
- * In order to use a custom rule in your form, you need to register it
- * first. For regular expressions, one can directly use the 'regex' type
- * rule in addRule(), this is faster than registering the rule.
- *
- * Functions and methods can be registered. Use the 'function' type.
- * When registering a method, specify the class name as second parameter.
- *
- * You can also register an HTML_QuickForm_Rule subclass with its own
- * validate() method.
- *
- * @param string $ruleName Name of validation rule
- * @param string $type Either: 'regex', 'function' or null
- * @param string $data1 Name of function, regular expression or
- * HTML_QuickForm_Rule object class name
- * @param string $data2 Object parent of above function or HTML_QuickForm_Rule file path
- * @access public
- * @return void
- */
- function registerRule($ruleName, $type, $data1, $data2 = null)
- {
- $type = strtolower($type);
- if ($type == 'regex') {
- // Regular expression
- $rule =& $this->getRule('regex');
- $rule->addData($ruleName, $data1);
- $GLOBALS['_HTML_QuickForm_registered_rules'][$ruleName] = $GLOBALS['_HTML_QuickForm_registered_rules']['regex'];
-
- } elseif ($type == 'function' || $type == 'callback') {
- // Callback function
- $rule =& $this->getRule('callback');
- $rule->addData($ruleName, $data1, $data2, 'function' == $type);
- $GLOBALS['_HTML_QuickForm_registered_rules'][$ruleName] = $GLOBALS['_HTML_QuickForm_registered_rules']['callback'];
-
- } elseif (is_object($data1)) {
- // An instance of HTML_QuickForm_Rule
- $this->_rules[strtolower(get_class($data1))] = $data1;
- $GLOBALS['_HTML_QuickForm_registered_rules'][$ruleName] = array(strtolower(get_class($data1)), null);
-
- } else {
- // Rule class name
- $GLOBALS['_HTML_QuickForm_registered_rules'][$ruleName] = array(strtolower($data1), $data2);
- }
- } // end func registerRule
-
- /**
- * Returns a reference to the requested rule object
- *
- * @param string $ruleName Name of the requested rule
- * @access public
- * @return HTML_QuickForm_Rule
- */
- function &getRule($ruleName)
- {
- list($class, $path) = $GLOBALS['_HTML_QuickForm_registered_rules'][$ruleName];
-
- if (!isset($this->_rules[$class])) {
- if (!empty($path)) {
- include_once($path);
- }
- $this->_rules[$class] = new $class();
- }
- $this->_rules[$class]->setName($ruleName);
- return $this->_rules[$class];
- } // end func getRule
-
- /**
- * Performs validation on the given values
- *
- * @param string $ruleName Name of the rule to be used
- * @param mixed $values Can be a scalar or an array of values
- * to be validated
- * @param mixed $options Options used by the rule
- * @param mixed $multiple Whether to validate an array of values altogether
- * @access public
- * @return mixed true if no error found, int of valid values (when an array of values is given) or false if error
- */
- function validate($ruleName, $values, $options = null, $multiple = false)
- {
- $rule =& $this->getRule($ruleName);
-
- if (is_array($values) && !$multiple) {
- $result = 0;
- foreach ($values as $value) {
- if ($rule->validate($value, $options) === true) {
- $result++;
- }
- }
- return ($result == 0) ? false : $result;
- } else {
- return $rule->validate($values, $options);
- }
- } // end func validate
-
- /**
- * Returns the validation test in javascript code
- *
- * @param array|HTML_QuickForm_element Element(s) the rule applies to
- * @param string Element name, in case $element is
- * not an array
- * @param array Rule data
- * @access public
- * @return string JavaScript for the rule
- */
- function getValidationScript(&$element, $elementName, $ruleData)
- {
- $reset = (isset($ruleData['reset'])) ? $ruleData['reset'] : false;
- $rule =& $this->getRule($ruleData['type']);
- if (!is_array($element)) {
- list($jsValue, $jsReset) = $this->_getJsValue($element, $elementName, $reset, null);
- } else {
- $jsValue = " value = new Array();\n";
- $jsReset = '';
- for ($i = 0; $i < count($element); $i++) {
- list($tmp_value, $tmp_reset) = $this->_getJsValue($element[$i], $element[$i]->getName(), $reset, $i);
- $jsValue .= "\n" . $tmp_value;
- $jsReset .= $tmp_reset;
- }
- }
- $jsField = isset($ruleData['group'])? $ruleData['group']: $elementName;
- list ($jsPrefix, $jsCheck) = $rule->getValidationScript($ruleData['format']);
- if (!isset($ruleData['howmany'])) {
- $js = $jsValue . "\n" . $jsPrefix .
- " if (" . str_replace('{jsVar}', 'value', $jsCheck) . " && !errFlag['{$jsField}']) {\n" .
- " errFlag['{$jsField}'] = true;\n" .
- " _qfMsg = _qfMsg + '\\n - {$ruleData['message']}';\n" .
- $jsReset .
- " }\n";
- } else {
- $js = $jsValue . "\n" . $jsPrefix .
- " var res = 0;\n" .
- " for (var i = 0; i < value.length; i++) {\n" .
- " if (!(" . str_replace('{jsVar}', 'value[i]', $jsCheck) . ")) {\n" .
- " res++;\n" .
- " }\n" .
- " }\n" .
- " if (res < {$ruleData['howmany']} && !errFlag['{$jsField}']) {\n" .
- " errFlag['{$jsField}'] = true;\n" .
- " _qfMsg = _qfMsg + '\\n - {$ruleData['message']}';\n" .
- $jsReset .
- " }\n";
- }
- return $js;
- } // end func getValidationScript
-
-
- /**
- * Returns JavaScript to get and to reset the element's value
- *
- * @access private
- * @param HTML_QuickForm_element element being processed
- * @param string element's name
- * @param bool whether to generate JavaScript to reset
- * the value
- * @param integer value's index in the array (only used for
- * multielement rules)
- * @return array first item is value javascript, second is reset
- */
- function _getJsValue(&$element, $elementName, $reset = false, $index = null)
- {
- $jsIndex = isset($index)? '[' . $index . ']': '';
- $tmp_reset = $reset? " var field = frm.elements['$elementName'];\n": '';
- if (is_a($element, 'html_quickform_group')) {
- $value = " _qfGroups['{$elementName}'] = {";
- $elements =& $element->getElements();
- for ($i = 0, $count = count($elements); $i < $count; $i++) {
- $append = ($elements[$i]->getType() == 'select' && $elements[$i]->getMultiple())? '[]': '';
- $value .= "'" . $element->getElementName($i) . $append . "': true" .
- ($i < $count - 1? ', ': '');
- }
- $value .=
- "};\n" .
- " value{$jsIndex} = new Array();\n" .
- " var valueIdx = 0;\n" .
- " for (var i = 0; i < frm.elements.length; i++) {\n" .
- " var _element = frm.elements[i];\n" .
- " if (_element.name in _qfGroups['{$elementName}']) {\n" .
- " switch (_element.type) {\n" .
- " case 'checkbox':\n" .
- " case 'radio':\n" .
- " if (_element.checked) {\n" .
- " value{$jsIndex}[valueIdx++] = _element.value;\n" .
- " }\n" .
- " break;\n" .
- " case 'select-one':\n" .
- " if (-1 != _element.selectedIndex) {\n" .
- " value{$jsIndex}[valueIdx++] = _element.options[_element.selectedIndex].value;\n" .
- " }\n" .
- " break;\n" .
- " case 'select-multiple':\n" .
- " var tmpVal = new Array();\n" .
- " var tmpIdx = 0;\n" .
- " for (var j = 0; j < _element.options.length; j++) {\n" .
- " if (_element.options[j].selected) {\n" .
- " tmpVal[tmpIdx++] = _element.options[j].value;\n" .
- " }\n" .
- " }\n" .
- " if (tmpIdx > 0) {\n" .
- " value{$jsIndex}[valueIdx++] = tmpVal;\n" .
- " }\n" .
- " break;\n" .
- " default:\n" .
- " value{$jsIndex}[valueIdx++] = _element.value;\n" .
- " }\n" .
- " }\n" .
- " }\n";
- if ($reset) {
- $tmp_reset =
- " for (var i = 0; i < frm.elements.length; i++) {\n" .
- " var _element = frm.elements[i];\n" .
- " if (_element.name in _qfGroups['{$elementName}']) {\n" .
- " switch (_element.type) {\n" .
- " case 'checkbox':\n" .
- " case 'radio':\n" .
- " _element.checked = _element.defaultChecked;\n" .
- " break;\n" .
- " case 'select-one':\n" .
- " case 'select-multiple':\n" .
- " for (var j = 0; j < _element.options.length; j++) {\n" .
- " _element.options[j].selected = _element.options[j].defaultSelected;\n" .
- " }\n" .
- " break;\n" .
- " default:\n" .
- " _element.value = _element.defaultValue;\n" .
- " }\n" .
- " }\n" .
- " }\n";
- }
-
- } elseif ($element->getType() == 'select') {
- if ($element->getMultiple()) {
- $elementName .= '[]';
- $value =
- " value{$jsIndex} = new Array();\n" .
- " var valueIdx = 0;\n" .
- " for (var i = 0; i < frm.elements['{$elementName}'].options.length; i++) {\n" .
- " if (frm.elements['{$elementName}'].options[i].selected) {\n" .
- " value{$jsIndex}[valueIdx++] = frm.elements['{$elementName}'].options[i].value;\n" .
- " }\n" .
- " }\n";
- } else {
- $value = " value{$jsIndex} = frm.elements['{$elementName}'].selectedIndex == -1? '': frm.elements['{$elementName}'].options[frm.elements['{$elementName}'].selectedIndex].value;\n";
- }
- if ($reset) {
- $tmp_reset .=
- " for (var i = 0; i < field.options.length; i++) {\n" .
- " field.options[i].selected = field.options[i].defaultSelected;\n" .
- " }\n";
- }
-
- } elseif ($element->getType() == 'checkbox') {
- if (is_a($element, 'html_quickform_advcheckbox')) {
- $value = " value{$jsIndex} = frm.elements['$elementName'][1].checked? frm.elements['$elementName'][1].value: frm.elements['$elementName'][0].value;\n";
- $tmp_reset .= $reset ? " field[1].checked = field[1].defaultChecked;\n" : '';
- } else {
- $value = " value{$jsIndex} = frm.elements['$elementName'].checked? '1': '';\n";
- $tmp_reset .= $reset ? " field.checked = field.defaultChecked;\n" : '';
- }
-
- } elseif ($element->getType() == 'radio') {
- $value = " value{$jsIndex} = '';\n" .
- // Fix for bug #5644
- " var els = 'length' in frm.elements['$elementName']? frm.elements['$elementName']: [ frm.elements['$elementName'] ];\n" .
- " for (var i = 0; i < els.length; i++) {\n" .
- " if (els[i].checked) {\n" .
- " value{$jsIndex} = els[i].value;\n" .
- " }\n" .
- " }";
- if ($reset) {
- $tmp_reset .= " for (var i = 0; i < field.length; i++) {\n" .
- " field[i].checked = field[i].defaultChecked;\n" .
- " }";
- }
-
- } else {
- $value = " value{$jsIndex} = frm.elements['$elementName'].value;";
- $tmp_reset .= ($reset) ? " field.value = field.defaultValue;\n" : '';
- }
- return array($value, $tmp_reset);
- }
-} // end class HTML_QuickForm_RuleRegistry
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * HTML class for an advanced checkbox type field
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Jason Rust <jrust@php.net>
- * @author Alexey Borzov <avb@php.net>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * HTML class for a checkbox type field
- */
-require_once 'HTML/QuickForm/checkbox.php';
-
-/**
- * HTML class for an advanced checkbox type field
- *
- * Basically this fixes a problem that HTML has had
- * where checkboxes can only pass a single value (the
- * value of the checkbox when checked). A value for when
- * the checkbox is not checked cannot be passed, and
- * furthermore the checkbox variable doesn't even exist if
- * the checkbox was submitted unchecked.
- *
- * It works by prepending a hidden field with the same name and
- * another "unchecked" value to the checbox. If the checkbox is
- * checked, PHP overwrites the value of the hidden field with
- * its value.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Jason Rust <jrust@php.net>
- * @author Alexey Borzov <avb@php.net>
- * @version Release: 3.2.16
- * @since 2.0
- */
-class HTML_QuickForm_advcheckbox extends HTML_QuickForm_checkbox
-{
- // {{{ properties
-
- /**
- * The values passed by the hidden elment
- *
- * @var array
- * @access private
- */
- var $_values = null;
-
- /**
- * The default value
- *
- * @var boolean
- * @access private
- */
- var $_currentValue = null;
-
- // }}}
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string $elementName (optional)Input field name attribute
- * @param string $elementLabel (optional)Input field label
- * @param string $text (optional)Text to put after the checkbox
- * @param mixed $attributes (optional)Either a typical HTML attribute string
- * or an associative array
- * @param mixed $values (optional)Values to pass if checked or not checked
- *
- * @since 1.0
- * @access public
- * @return void
- */
- function HTML_QuickForm_advcheckbox($elementName=null, $elementLabel=null, $text=null, $attributes=null, $values=null)
- {
- $this->HTML_QuickForm_checkbox($elementName, $elementLabel, $text, $attributes);
- $this->setValues($values);
- } //end constructor
-
- // }}}
- // {{{ getPrivateName()
-
- /**
- * Gets the private name for the element
- *
- * @param string $elementName The element name to make private
- *
- * @access public
- * @return string
- *
- * @deprecated Deprecated since 3.2.6, both generated elements have the same name
- */
- function getPrivateName($elementName)
- {
- return '__'.$elementName;
- }
-
- // }}}
- // {{{ getOnclickJs()
-
- /**
- * Create the javascript for the onclick event which will
- * set the value of the hidden field
- *
- * @param string $elementName The element name
- *
- * @access public
- * @return string
- *
- * @deprecated Deprecated since 3.2.6, this element no longer uses any javascript
- */
- function getOnclickJs($elementName)
- {
- $onclickJs = 'if (this.checked) { this.form[\''.$elementName.'\'].value=\''.addcslashes($this->_values[1], '\'').'\'; }';
- $onclickJs .= 'else { this.form[\''.$elementName.'\'].value=\''.addcslashes($this->_values[0], '\'').'\'; }';
- return $onclickJs;
- }
-
- // }}}
- // {{{ setValues()
-
- /**
- * Sets the values used by the hidden element
- *
- * @param mixed $values The values, either a string or an array
- *
- * @access public
- * @return void
- */
- function setValues($values)
- {
- if (empty($values)) {
- // give it default checkbox behavior
- $this->_values = array('', 1);
- } elseif (is_scalar($values)) {
- // if it's string, then assume the value to
- // be passed is for when the element is checked
- $this->_values = array('', $values);
- } else {
- $this->_values = $values;
- }
- $this->updateAttributes(array('value' => $this->_values[1]));
- $this->setChecked($this->_currentValue == $this->_values[1]);
- }
-
- // }}}
- // {{{ setValue()
-
- /**
- * Sets the element's value
- *
- * @param mixed Element's value
- * @access public
- */
- function setValue($value)
- {
- $this->setChecked(isset($this->_values[1]) && $value == $this->_values[1]);
- $this->_currentValue = $value;
- }
-
- // }}}
- // {{{ getValue()
-
- /**
- * Returns the element's value
- *
- * @access public
- * @return mixed
- */
- function getValue()
- {
- if (is_array($this->_values)) {
- return $this->_values[$this->getChecked()? 1: 0];
- } else {
- return null;
- }
- }
-
- // }}}
- // {{{ toHtml()
-
- /**
- * Returns the checkbox element in HTML
- * and the additional hidden element in HTML
- *
- * @access public
- * @return string
- */
- function toHtml()
- {
- if ($this->_flagFrozen) {
- return parent::toHtml();
- } else {
- return '<input' . $this->_getAttrString(array(
- 'type' => 'hidden',
- 'name' => $this->getName(),
- 'value' => $this->_values[0]
- )) . ' />' . parent::toHtml();
-
- }
- } //end func toHtml
-
- // }}}
- // {{{ getFrozenHtml()
-
- /**
- * Unlike checkbox, this has to append a hidden input in both
- * checked and non-checked states
- */
- function getFrozenHtml()
- {
- return ($this->getChecked()? '<tt>[x]</tt>': '<tt>[ ]</tt>') .
- $this->_getPersistantData();
- }
-
- // }}}
- // {{{ onQuickFormEvent()
-
- /**
- * Called by HTML_QuickForm whenever form event is made on this element
- *
- * @param string $event Name of event
- * @param mixed $arg event arguments
- * @param object &$caller calling object
- * @since 1.0
- * @access public
- * @return void
- */
- function onQuickFormEvent($event, $arg, &$caller)
- {
- switch ($event) {
- case 'updateValue':
- // constant values override both default and submitted ones
- // default values are overriden by submitted
- $value = $this->_findValue($caller->_constantValues);
- if (null === $value) {
- $value = $this->_findValue($caller->_submitValues);
- if (null === $value) {
- $value = $this->_findValue($caller->_defaultValues);
- }
- }
- if (null !== $value) {
- $this->setValue($value);
- }
- break;
- default:
- parent::onQuickFormEvent($event, $arg, $caller);
- }
- return true;
- } // end func onQuickFormLoad
-
- // }}}
- // {{{ exportValue()
-
- /**
- * This element has a value even if it is not checked, thus we override
- * checkbox's behaviour here
- */
- function exportValue(&$submitValues, $assoc = false)
- {
- $value = $this->_findValue($submitValues);
- if (null === $value) {
- $value = $this->getValue();
- } elseif (is_array($this->_values) && ($value != $this->_values[0]) && ($value != $this->_values[1])) {
- $value = null;
- }
- return $this->_prepareValue($value, $assoc);
- }
- // }}}
-} //end class HTML_QuickForm_advcheckbox
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * HTML class for an autocomplete element
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Matteo Di Giovinazzo <matteodg@infinito.it>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * HTML class for a text field
- */
-require_once 'HTML/QuickForm/text.php';
-
-/**
- * HTML class for an autocomplete element
- *
- * Creates an HTML input text element that
- * at every keypressed javascript event checks in an array of options
- * if there's a match and autocompletes the text in case of match.
- *
- * For the JavaScript code thanks to Martin Honnen and Nicholas C. Zakas
- * See {@link http://www.faqts.com/knowledge_base/view.phtml/aid/13562} and
- * {@link http://www.sitepoint.com/article/1220}
- *
- * Example:
- * <code>
- * $autocomplete =& $form->addElement('autocomplete', 'fruit', 'Favourite fruit:');
- * $options = array("Apple", "Orange", "Pear", "Strawberry");
- * $autocomplete->setOptions($options);
- * </code>
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Matteo Di Giovinazzo <matteodg@infinito.it>
- * @version Release: 3.2.16
- * @since 3.2
- */
-class HTML_QuickForm_autocomplete extends HTML_QuickForm_text
-{
- // {{{ properties
-
- /**
- * Options for the autocomplete input text element
- *
- * @var array
- * @access private
- */
- var $_options = array();
-
- /**
- * "One-time" javascript (containing functions), see bug #4611
- *
- * @var string
- * @access private
- */
- var $_js = '';
-
- // }}}
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string $elementName (optional)Input field name attribute
- * @param string $elementLabel (optional)Input field label in form
- * @param array $options (optional)Autocomplete options
- * @param mixed $attributes (optional)Either a typical HTML attribute string
- * or an associative array. Date format is passed along the attributes.
- * @access public
- * @return void
- */
- function HTML_QuickForm_autocomplete($elementName = null, $elementLabel = null, $options = null, $attributes = null)
- {
- $this->HTML_QuickForm_text($elementName, $elementLabel, $attributes);
- $this->_persistantFreeze = true;
- $this->_type = 'autocomplete';
- if (isset($options)) {
- $this->setOptions($options);
- }
- } //end constructor
-
- // }}}
- // {{{ setOptions()
-
- /**
- * Sets the options for the autocomplete input text element
- *
- * @param array $options Array of options for the autocomplete input text element
- * @access public
- * @return void
- */
- function setOptions($options)
- {
- $this->_options = array_values($options);
- } // end func setOptions
-
- // }}}
- // {{{ toHtml()
-
- /**
- * Returns Html for the autocomplete input text element
- *
- * @access public
- * @return string
- */
- function toHtml()
- {
- // prevent problems with grouped elements
- $arrayName = str_replace(array('[', ']'), array('__', ''), $this->getName()) . '_values';
-
- $this->updateAttributes(array(
- 'onkeypress' => 'return window.autocomplete(this, event, ' . $arrayName . ');'
- ));
- if ($this->_flagFrozen) {
- $js = '';
- } else {
- $js = "<script type=\"text/javascript\">\n//<![CDATA[\n";
- if (!defined('HTML_QUICKFORM_AUTOCOMPLETE_EXISTS')) {
- $this->_js .= <<<EOS
-
-/* begin javascript for autocomplete */
-function setSelectionRange(input, selectionStart, selectionEnd) {
- if (input.setSelectionRange) {
- input.setSelectionRange(selectionStart, selectionEnd);
- }
- else if (input.createTextRange) {
- var range = input.createTextRange();
- range.collapse(true);
- range.moveEnd("character", selectionEnd);
- range.moveStart("character", selectionStart);
- range.select();
- }
- input.focus();
-}
-
-function setCaretToPosition(input, position) {
- setSelectionRange(input, position, position);
-}
-
-function replaceSelection (input, replaceString) {
- var len = replaceString.length;
- if (input.setSelectionRange) {
- var selectionStart = input.selectionStart;
- var selectionEnd = input.selectionEnd;
-
- input.value = input.value.substring(0, selectionStart) + replaceString + input.value.substring(selectionEnd);
- input.selectionStart = selectionStart + len;
- input.selectionEnd = selectionStart + len;
- }
- else if (document.selection) {
- var range = document.selection.createRange();
- var saved_range = range.duplicate();
-
- if (range.parentElement() == input) {
- range.text = replaceString;
- range.moveEnd("character", saved_range.selectionStart + len);
- range.moveStart("character", saved_range.selectionStart + len);
- range.select();
- }
- }
- input.focus();
-}
-
-
-function autocompleteMatch (text, values) {
- for (var i = 0; i < values.length; i++) {
- if (values[i].toUpperCase().indexOf(text.toUpperCase()) == 0) {
- return values[i];
- }
- }
-
- return null;
-}
-
-function autocomplete(textbox, event, values) {
- if (textbox.setSelectionRange || textbox.createTextRange) {
- switch (event.keyCode) {
- case 38: // up arrow
- case 40: // down arrow
- case 37: // left arrow
- case 39: // right arrow
- case 33: // page up
- case 34: // page down
- case 36: // home
- case 35: // end
- case 13: // enter
- case 9: // tab
- case 27: // esc
- case 16: // shift
- case 17: // ctrl
- case 18: // alt
- case 20: // caps lock
- case 8: // backspace
- case 46: // delete
- return true;
- break;
-
- default:
- var c = String.fromCharCode(
- (event.charCode == undefined) ? event.keyCode : event.charCode
- );
- replaceSelection(textbox, c);
- sMatch = autocompleteMatch(textbox.value, values);
- var len = textbox.value.length;
-
- if (sMatch != null) {
- textbox.value = sMatch;
- setSelectionRange(textbox, len, textbox.value.length);
- }
- return false;
- }
- }
- else {
- return true;
- }
-}
-/* end javascript for autocomplete */
-
-EOS;
- define('HTML_QUICKFORM_AUTOCOMPLETE_EXISTS', true);
- }
- $jsEscape = array(
- "\r" => '\r',
- "\n" => '\n',
- "\t" => '\t',
- "'" => "\\'",
- '"' => '\"',
- '\\' => '\\\\'
- );
-
- $js .= $this->_js;
- $js .= 'var ' . $arrayName . " = new Array();\n";
- for ($i = 0; $i < count($this->_options); $i++) {
- $js .= $arrayName . '[' . $i . "] = '" . strtr($this->_options[$i], $jsEscape) . "';\n";
- }
- $js .= "//]]>\n</script>";
- }
- return $js . parent::toHtml();
- }// end func toHtml
-
- // }}}
-} // end class HTML_QuickForm_autocomplete
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * HTML class for an <input type="button" /> elements
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Base class for <input /> form elements
- */
-require_once 'HTML/QuickForm/input.php';
-
-/**
- * HTML class for an <input type="button" /> elements
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @version Release: 3.2.16
- * @since 1.0
- */
-class HTML_QuickForm_button extends HTML_QuickForm_input
-{
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string $elementName (optional)Input field name attribute
- * @param string $value (optional)Input field value
- * @param mixed $attributes (optional)Either a typical HTML attribute string
- * or an associative array
- * @since 1.0
- * @access public
- * @return void
- */
- function HTML_QuickForm_button($elementName=null, $value=null, $attributes=null)
- {
- HTML_QuickForm_input::HTML_QuickForm_input($elementName, null, $attributes);
- $this->_persistantFreeze = false;
- $this->setValue($value);
- $this->setType('button');
- } //end constructor
-
- // }}}
- // {{{ freeze()
-
- /**
- * Freeze the element so that only its value is returned
- *
- * @access public
- * @return void
- */
- function freeze()
- {
- return false;
- } //end func freeze
-
- // }}}
-
-} //end class HTML_QuickForm_button
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * HTML class for a checkbox type field
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Alexey Borzov <avb@php.net>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Base class for <input /> form elements
- */
-require_once 'HTML/QuickForm/input.php';
-
-/**
- * HTML class for a checkbox type field
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Alexey Borzov <avb@php.net>
- * @version Release: 3.2.16
- * @since 1.0
- */
-class HTML_QuickForm_checkbox extends HTML_QuickForm_input
-{
- // {{{ properties
-
- /**
- * Checkbox display text
- * @var string
- * @since 1.1
- * @access private
- */
- var $_text = '';
-
- // }}}
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string $elementName (optional)Input field name attribute
- * @param string $elementLabel (optional)Input field value
- * @param string $text (optional)Checkbox display text
- * @param mixed $attributes (optional)Either a typical HTML attribute string
- * or an associative array
- * @since 1.0
- * @access public
- * @return void
- */
- function HTML_QuickForm_checkbox($elementName=null, $elementLabel=null, $text='', $attributes=null)
- {
- HTML_QuickForm_input::HTML_QuickForm_input($elementName, $elementLabel, $attributes);
- $this->_persistantFreeze = true;
- $this->_text = $text;
- $this->setType('checkbox');
- $this->updateAttributes(array('value'=>1));
- $this->_generateId();
- } //end constructor
-
- // }}}
- // {{{ setChecked()
-
- /**
- * Sets whether a checkbox is checked
- *
- * @param bool $checked Whether the field is checked or not
- * @since 1.0
- * @access public
- * @return void
- */
- function setChecked($checked)
- {
- if (!$checked) {
- $this->removeAttribute('checked');
- } else {
- $this->updateAttributes(array('checked'=>'checked'));
- }
- } //end func setChecked
-
- // }}}
- // {{{ getChecked()
-
- /**
- * Returns whether a checkbox is checked
- *
- * @since 1.0
- * @access public
- * @return bool
- */
- function getChecked()
- {
- return (bool)$this->getAttribute('checked');
- } //end func getChecked
-
- // }}}
- // {{{ toHtml()
-
- /**
- * Returns the checkbox element in HTML
- *
- * @since 1.0
- * @access public
- * @return string
- */
- function toHtml()
- {
- if (0 == strlen($this->_text)) {
- $label = '';
- } elseif ($this->_flagFrozen) {
- $label = $this->_text;
- } else {
- $label = '<label for="' . $this->getAttribute('id') . '">' . $this->_text . '</label>';
- }
- return HTML_QuickForm_input::toHtml() . $label;
- } //end func toHtml
-
- // }}}
- // {{{ getFrozenHtml()
-
- /**
- * Returns the value of field without HTML tags
- *
- * @since 1.0
- * @access public
- * @return string
- */
- function getFrozenHtml()
- {
- if ($this->getChecked()) {
- return '<tt>[x]</tt>' .
- $this->_getPersistantData();
- } else {
- return '<tt>[ ]</tt>';
- }
- } //end func getFrozenHtml
-
- // }}}
- // {{{ setText()
-
- /**
- * Sets the checkbox text
- *
- * @param string $text
- * @since 1.1
- * @access public
- * @return void
- */
- function setText($text)
- {
- $this->_text = $text;
- } //end func setText
-
- // }}}
- // {{{ getText()
-
- /**
- * Returns the checkbox text
- *
- * @since 1.1
- * @access public
- * @return string
- */
- function getText()
- {
- return $this->_text;
- } //end func getText
-
- // }}}
- // {{{ setValue()
-
- /**
- * Sets the value of the form element
- *
- * @param string $value Default value of the form element
- * @since 1.0
- * @access public
- * @return void
- */
- function setValue($value)
- {
- return $this->setChecked($value);
- } // end func setValue
-
- // }}}
- // {{{ getValue()
-
- /**
- * Returns the value of the form element
- *
- * @since 1.0
- * @access public
- * @return bool
- */
- function getValue()
- {
- return $this->getChecked();
- } // end func getValue
-
- // }}}
- // {{{ onQuickFormEvent()
-
- /**
- * Called by HTML_QuickForm whenever form event is made on this element
- *
- * @param string $event Name of event
- * @param mixed $arg event arguments
- * @param object &$caller calling object
- * @since 1.0
- * @access public
- * @return void
- */
- function onQuickFormEvent($event, $arg, &$caller)
- {
- switch ($event) {
- case 'updateValue':
- // constant values override both default and submitted ones
- // default values are overriden by submitted
- $value = $this->_findValue($caller->_constantValues);
- if (null === $value) {
- // if no boxes were checked, then there is no value in the array
- // yet we don't want to display default value in this case
- if ($caller->isSubmitted()) {
- $value = $this->_findValue($caller->_submitValues);
- } else {
- $value = $this->_findValue($caller->_defaultValues);
- }
- }
- if (null !== $value || $caller->isSubmitted()) {
- $this->setChecked($value);
- }
- break;
- case 'setGroupValue':
- $this->setChecked($arg);
- break;
- default:
- parent::onQuickFormEvent($event, $arg, $caller);
- }
- return true;
- } // end func onQuickFormEvent
-
- // }}}
- // {{{ exportValue()
-
- /**
- * Return true if the checkbox is checked, null if it is not checked (getValue() returns false)
- */
- function exportValue(&$submitValues, $assoc = false)
- {
- $value = $this->_findValue($submitValues);
- if (null === $value) {
- $value = $this->getChecked()? true: null;
- }
- return $this->_prepareValue($value, $assoc);
- }
-
- // }}}
-} //end class HTML_QuickForm_checkbox
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Class for a group of elements used to input dates (and times).
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Alexey Borzov <avb@php.net>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Class for a group of form elements
- */
-require_once 'HTML/QuickForm/group.php';
-/**
- * Class for <select></select> elements
- */
-require_once 'HTML/QuickForm/select.php';
-
-/**
- * Class for a group of elements used to input dates (and times).
- *
- * Inspired by original 'date' element but reimplemented as a subclass
- * of HTML_QuickForm_group
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Alexey Borzov <avb@php.net>
- * @version Release: 3.2.16
- * @since 3.1
- */
-class HTML_QuickForm_date extends HTML_QuickForm_group
-{
- // {{{ properties
-
- /**
- * Various options to control the element's display.
- *
- * @access private
- * @var array
- */
- var $_options = array(
- 'language' => 'en',
- 'format' => 'dMY',
- 'minYear' => 2001,
- 'maxYear' => null, // set in the constructor
- 'addEmptyOption' => false,
- 'emptyOptionValue' => '',
- 'emptyOptionText' => ' ',
- 'optionIncrement' => array('i' => 1, 's' => 1)
- );
-
- /**
- * These complement separators, they are appended to the resultant HTML
- * @access private
- * @var array
- */
- var $_wrap = array('', '');
-
- /**
- * Options in different languages
- *
- * Note to potential translators: to avoid encoding problems please send
- * your translations with "weird" letters encoded as HTML Unicode entities
- *
- * @access private
- * @var array
- */
- var $_locale = array(
- 'en' => array (
- 'weekdays_short'=> array ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'),
- 'weekdays_long' => array ('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'),
- 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'),
- 'months_long' => array ('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December')
- ),
- 'de' => array (
- 'weekdays_short'=> array ('So', 'Mon', 'Di', 'Mi', 'Do', 'Fr', 'Sa'),
- 'weekdays_long' => array ('Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'),
- 'months_short' => array ('Jan', 'Feb', 'März', 'April', 'Mai', 'Juni', 'Juli', 'Aug', 'Sept', 'Okt', 'Nov', 'Dez'),
- 'months_long' => array ('Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember')
- ),
- 'fr' => array (
- 'weekdays_short'=> array ('Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'),
- 'weekdays_long' => array ('Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'),
- 'months_short' => array ('Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Juin', 'Juil', 'Août', 'Sep', 'Oct', 'Nov', 'Déc'),
- 'months_long' => array ('Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre')
- ),
- 'hu' => array (
- 'weekdays_short'=> array ('V', 'H', 'K', 'Sze', 'Cs', 'P', 'Szo'),
- 'weekdays_long' => array ('vasárnap', 'hétfő', 'kedd', 'szerda', 'csütörtök', 'péntek', 'szombat'),
- 'months_short' => array ('jan', 'feb', 'márc', 'ápr', 'máj', 'jún', 'júl', 'aug', 'szept', 'okt', 'nov', 'dec'),
- 'months_long' => array ('január', 'február', 'március', 'április', 'május', 'június', 'július', 'augusztus', 'szeptember', 'október', 'november', 'december')
- ),
- 'pl' => array (
- 'weekdays_short'=> array ('Nie', 'Pn', 'Wt', 'Śr', 'Czw', 'Pt', 'Sob'),
- 'weekdays_long' => array ('Niedziela', 'Poniedziałek', 'Wtorek', 'Środa', 'Czwartek', 'Piątek', 'Sobota'),
- 'months_short' => array ('Sty', 'Lut', 'Mar', 'Kwi', 'Maj', 'Cze', 'Lip', 'Sie', 'Wrz', 'Paź', 'Lis', 'Gru'),
- 'months_long' => array ('Styczeń', 'Luty', 'Marzec', 'Kwiecień', 'Maj', 'Czerwiec', 'Lipiec', 'Sierpień', 'Wrzesień', 'Październik', 'Listopad', 'Grudzień')
- ),
- 'sl' => array (
- 'weekdays_short'=> array ('Ned', 'Pon', 'Tor', 'Sre', 'Cet', 'Pet', 'Sob'),
- 'weekdays_long' => array ('Nedelja', 'Ponedeljek', 'Torek', 'Sreda', 'Cetrtek', 'Petek', 'Sobota'),
- 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Avg', 'Sep', 'Okt', 'Nov', 'Dec'),
- 'months_long' => array ('Januar', 'Februar', 'Marec', 'April', 'Maj', 'Junij', 'Julij', 'Avgust', 'September', 'Oktober', 'November', 'December')
- ),
- 'ru' => array (
- 'weekdays_short'=> array ('Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'),
- 'weekdays_long' => array ('Воскресенье', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота'),
- 'months_short' => array ('Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'),
- 'months_long' => array ('Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь')
- ),
- 'es' => array (
- 'weekdays_short'=> array ('Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb'),
- 'weekdays_long' => array ('Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'),
- 'months_short' => array ('Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'),
- 'months_long' => array ('Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre')
- ),
- 'da' => array (
- 'weekdays_short'=> array ('Søn', 'Man', 'Tir', 'Ons', 'Tor', 'Fre', 'Lør'),
- 'weekdays_long' => array ('Søndag', 'Mandag', 'Tirsdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lørdag'),
- 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'),
- 'months_long' => array ('Januar', 'Februar', 'Marts', 'April', 'Maj', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'December')
- ),
- 'is' => array (
- 'weekdays_short'=> array ('Sun', 'Mán', 'Þri', 'Mið', 'Fim', 'Fös', 'Lau'),
- 'weekdays_long' => array ('Sunnudagur', 'Mánudagur', 'Þriðjudagur', 'Miðvikudagur', 'Fimmtudagur', 'Föstudagur', 'Laugardagur'),
- 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Maí', 'Jún', 'Júl', 'Ágú', 'Sep', 'Okt', 'Nóv', 'Des'),
- 'months_long' => array ('Janúar', 'Febrúar', 'Mars', 'Apríl', 'Maí', 'Júní', 'Júlí', 'Ágúst', 'September', 'Október', 'Nóvember', 'Desember')
- ),
- 'it' => array (
- 'weekdays_short'=> array ('Dom', 'Lun', 'Mar', 'Mer', 'Gio', 'Ven', 'Sab'),
- 'weekdays_long' => array ('Domenica', 'Lunedì', 'Martedì', 'Mercoledì', 'Giovedì', 'Venerdì', 'Sabato'),
- 'months_short' => array ('Gen', 'Feb', 'Mar', 'Apr', 'Mag', 'Giu', 'Lug', 'Ago', 'Set', 'Ott', 'Nov', 'Dic'),
- 'months_long' => array ('Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre', 'Dicembre')
- ),
- 'sk' => array (
- 'weekdays_short'=> array ('Ned', 'Pon', 'Uto', 'Str', 'Štv', 'Pia', 'Sob'),
- 'weekdays_long' => array ('Nedeža', 'Pondelok', 'Utorok', 'Streda', 'Štvrtok', 'Piatok', 'Sobota'),
- 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Máj', 'Jún', 'Júl', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'),
- 'months_long' => array ('Január', 'Február', 'Marec', 'Apríl', 'Máj', 'Jún', 'Júl', 'August', 'September', 'Október', 'November', 'December')
- ),
- 'cs' => array (
- 'weekdays_short'=> array ('Ne', 'Po', 'Út', 'St', 'Čt', 'Pá', 'So'),
- 'weekdays_long' => array ('Neděle', 'Pondělí', 'Úterý', 'Středa', 'Čtvrtek', 'Pátek', 'Sobota'),
- 'months_short' => array ('Led', 'Úno', 'Bře', 'Dub', 'Kvě', 'Čen', 'Čec', 'Srp', 'Zář', 'Říj', 'Lis', 'Pro'),
- 'months_long' => array ('Leden', 'Únor', 'Březen', 'Duben', 'Květen', 'Červen', 'Červenec', 'Srpen', 'Září', 'Říjen', 'Listopad', 'Prosinec')
- ),
- 'hy' => array (
- 'weekdays_short'=> array ('Կրկ', 'Երկ', 'Երք', 'Չրք', 'Հնգ', 'Ուր', 'Շբթ'),
- 'weekdays_long' => array ('Կիրակի', 'Երկուշաբթի', 'Երեքշաբթի', 'Չորեքշաբթի', 'Հինգշաբթի', 'Ուրբաթ', 'Շաբաթ'),
- 'months_short' => array ('Հնվ', 'Փտր', 'Մրտ', 'Ապր', 'Մյս', 'Հնս', 'Հլս', 'Օգս', 'Սպտ', 'Հկտ', 'Նյմ', 'Դկտ'),
- 'months_long' => array ('Հունվար', 'Փետրվար', 'Մարտ', 'Ապրիլ', 'Մայիս', 'Հունիս', 'Հուլիս', 'Օգոստոս', 'Սեպտեմբեր', 'Հոկտեմբեր', 'Նոյեմբեր', 'Դեկտեմբեր')
- ),
- 'nl' => array (
- 'weekdays_short'=> array ('Zo', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Za'),
- 'weekdays_long' => array ('Zondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrijdag', 'Zaterdag'),
- 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'),
- 'months_long' => array ('Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni', 'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December')
- ),
- 'et' => array (
- 'weekdays_short'=> array ('P', 'E', 'T', 'K', 'N', 'R', 'L'),
- 'weekdays_long' => array ('Pühapäev', 'Esmaspäev', 'Teisipäev', 'Kolmapäev', 'Neljapäev', 'Reede', 'Laupäev'),
- 'months_short' => array ('Jaan', 'Veebr', 'Märts', 'Aprill', 'Mai', 'Juuni', 'Juuli', 'Aug', 'Sept', 'Okt', 'Nov', 'Dets'),
- 'months_long' => array ('Jaanuar', 'Veebruar', 'Märts', 'Aprill', 'Mai', 'Juuni', 'Juuli', 'August', 'September', 'Oktoober', 'November', 'Detsember')
- ),
- 'tr' => array (
- 'weekdays_short'=> array ('Paz', 'Pzt', 'Sal', 'Çar', 'Per', 'Cum', 'Cts'),
- 'weekdays_long' => array ('Pazar', 'Pazartesi', 'Salı', 'Çarşamba', 'Perşembe', 'Cuma', 'Cumartesi'),
- 'months_short' => array ('Ock', 'Şbt', 'Mrt', 'Nsn', 'Mys', 'Hzrn', 'Tmmz', 'Ağst', 'Eyl', 'Ekm', 'Ksm', 'Arlk'),
- 'months_long' => array ('Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran', 'Temmuz', 'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık')
- ),
- 'no' => array (
- 'weekdays_short'=> array ('Søn', 'Man', 'Tir', 'Ons', 'Tor', 'Fre', 'Lør'),
- 'weekdays_long' => array ('Søndag', 'Mandag', 'Tirsdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lørdag'),
- 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Des'),
- 'months_long' => array ('Januar', 'Februar', 'Mars', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Desember')
- ),
- 'eo' => array (
- 'weekdays_short'=> array ('Dim', 'Lun', 'Mar', 'Mer', 'Ĵaŭ', 'Ven', 'Sab'),
- 'weekdays_long' => array ('Dimanĉo', 'Lundo', 'Mardo', 'Merkredo', 'Ĵaŭdo', 'Vendredo', 'Sabato'),
- 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Aŭg', 'Sep', 'Okt', 'Nov', 'Dec'),
- 'months_long' => array ('Januaro', 'Februaro', 'Marto', 'Aprilo', 'Majo', 'Junio', 'Julio', 'Aŭgusto', 'Septembro', 'Oktobro', 'Novembro', 'Decembro')
- ),
- 'ua' => array (
- 'weekdays_short'=> array('Ндл', 'Пнд', 'Втр', 'Срд', 'Чтв', 'Птн', 'Сбт'),
- 'weekdays_long' => array('Неділя', 'Понеділок', 'Вівторок', 'Середа', 'Четвер', 'П\'ятниця', 'Субота'),
- 'months_short' => array('Січ', 'Лют', 'Бер', 'Кві', 'Тра', 'Чер', 'Лип', 'Сер', 'Вер', 'Жов', 'Лис', 'Гру'),
- 'months_long' => array('Січень', 'Лютий', 'Березень', 'Квітень', 'Травень', 'Червень', 'Липень', 'Серпень', 'Вересень', 'Жовтень', 'Листопад', 'Грудень')
- ),
- 'ro' => array (
- 'weekdays_short'=> array ('Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sam'),
- 'weekdays_long' => array ('Duminica', 'Luni', 'Marti', 'Miercuri', 'Joi', 'Vineri', 'Sambata'),
- 'months_short' => array ('Ian', 'Feb', 'Mar', 'Apr', 'Mai', 'Iun', 'Iul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'),
- 'months_long' => array ('Ianuarie', 'Februarie', 'Martie', 'Aprilie', 'Mai', 'Iunie', 'Iulie', 'August', 'Septembrie', 'Octombrie', 'Noiembrie', 'Decembrie')
- ),
- 'he' => array (
- 'weekdays_short'=> array ('ראשון', 'שני', 'שלישי', 'רביעי', 'חמישי', 'שישי', 'שבת'),
- 'weekdays_long' => array ('יום ראשון', 'יום שני', 'יום שלישי', 'יום רביעי', 'יום חמישי', 'יום שישי', 'שבת'),
- 'months_short' => array ('ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר', 'נובמבר', 'דצמבר'),
- 'months_long' => array ('ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר', 'נובמבר', 'דצמבר')
- ),
- 'sv' => array (
- 'weekdays_short'=> array ('Sön', 'Mån', 'Tis', 'Ons', 'Tor', 'Fre', 'Lör'),
- 'weekdays_long' => array ('Söndag', 'Måndag', 'Tisdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lördag'),
- 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'),
- 'months_long' => array ('Januari', 'Februari', 'Mars', 'April', 'Maj', 'Juni', 'Juli', 'Augusti', 'September', 'Oktober', 'November', 'December')
- ),
- 'pt' => array (
- 'weekdays_short'=> array ('Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'),
- 'weekdays_long' => array ('Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'Sábado'),
- 'months_short' => array ('Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'),
- 'months_long' => array ('Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro')
- ),
- 'tw' => array (
- 'weekdays_short'=> array ('週日','週一', '週二','週三', '週四','週五', '週六'),
- 'weekdays_long' => array ('星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'),
- 'months_short' => array ('一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'),
- 'months_long' => array ('一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月')
- ),
- 'pt-br' => array (
- 'weekdays_short'=> array ('Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'),
- 'weekdays_long' => array ('Domingo', 'Segunda', 'Terça', 'Quarta', 'Quinta', 'Sexta', 'Sábado'),
- 'months_short' => array ('Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'),
- 'months_long' => array ('Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro')
- ),
- 'sr' => array (
- 'weekdays_short'=> array ('Нед', 'Пон', 'Уто', 'Сре', 'Чет', 'Пет', 'Суб'),
- 'weekdays_long' => array ('Недеља', 'Понедељак', 'Уторак', 'Среда', 'Четвртак', 'Петак', 'Субота'),
- 'months_short' => array ('Јан', 'Феб', 'Мар', 'Апр', 'Мај', 'Јун', 'Јул', 'Авг', 'Сеп', 'Окт', 'Нов', 'Дец'),
- 'months_long' => array ('Јануар', 'Фебруар', 'Март', 'Април', 'Мај', 'Јун', 'Јул', 'Август', 'Септембар', 'Октобар', 'Новембар', 'Децембар')
- ),
- 'el' => array (
- 'weekdays_short'=> array ('Δευ', 'Τρί', 'Τετ', 'Πέμ', 'Παρ', 'Σάβ', 'Κυρ'),
- 'weekdays_long' => array ('Δευτέρα', 'Τρίτη', 'Τετάρτη', 'Πέμπτη', 'Παρασκευή', 'Σάββατο', 'Κυριακή'),
- 'months_short' => array ('Ιαν', 'Φεβ', 'Μάρ', 'Απρ', 'Μάϊ', 'Ioύν', 'Ιούλ', 'Αύγ', 'Σεπ', 'Οκτ', 'Νοέ', 'Δεκ'),
- 'months_long' => array ('Ιανουάριος', 'Φεβρουάριος', 'Μάρτιος', 'Απρίλιος', 'Μάϊος', 'Ιούνιος', 'Ioύλιος', 'Αύγουστος', 'Σεπτέμβριος', 'Οκτώβριος', 'Νοέμβριος', 'Δεκέμβριος')
- )
- );
-
- // }}}
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * The following keys may appear in $options array:
- * - 'language': date language
- * - 'format': Format of the date, based on PHP's date() function.
- * The following characters are currently recognised in format string:
- * <pre>
- * D => Short names of days
- * l => Long names of days
- * d => Day numbers
- * M => Short names of months
- * F => Long names of months
- * m => Month numbers
- * Y => Four digit year
- * y => Two digit year
- * h => 12 hour format
- * H => 23 hour format
- * i => Minutes
- * s => Seconds
- * a => am/pm
- * A => AM/PM
- * </pre>
- * - 'minYear': Minimum year in year select
- * - 'maxYear': Maximum year in year select
- * - 'addEmptyOption': Should an empty option be added to the top of
- * each select box?
- * - 'emptyOptionValue': The value passed by the empty option.
- * - 'emptyOptionText': The text displayed for the empty option.
- * - 'optionIncrement': Step to increase the option values by (works for 'i' and 's')
- *
- * @access public
- * @param string Element's name
- * @param mixed Label(s) for an element
- * @param array Options to control the element's display
- * @param mixed Either a typical HTML attribute string or an associative array
- */
- function HTML_QuickForm_date($elementName = null, $elementLabel = null, $options = array(), $attributes = null)
- {
- $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes);
- $this->_persistantFreeze = true;
- $this->_appendName = true;
- $this->_type = 'date';
-
- // http://pear.php.net/bugs/bug.php?id=18171
- $this->_options['maxYear'] = date('Y');
-
- // set the options, do not bother setting bogus ones
- if (is_array($options)) {
- foreach ($options as $name => $value) {
- if ('language' == $name) {
- $this->_options['language'] = isset($this->_locale[$value])? $value: 'en';
- } elseif (isset($this->_options[$name])) {
- if (is_array($value) && is_array($this->_options[$name])) {
- $this->_options[$name] = @array_merge($this->_options[$name], $value);
- } else {
- $this->_options[$name] = $value;
- }
- }
- }
- }
- }
-
- // }}}
- // {{{ _createElements()
-
- function _createElements()
- {
- $this->_separator = $this->_elements = array();
- $separator = '';
- $locale =& $this->_locale[$this->_options['language']];
- $backslash = false;
- for ($i = 0, $length = strlen($this->_options['format']); $i < $length; $i++) {
- $sign = $this->_options['format']{$i};
- if ($backslash) {
- $backslash = false;
- $separator .= $sign;
- } else {
- $loadSelect = true;
- switch ($sign) {
- case 'D':
- // Sunday is 0 like with 'w' in date()
- $options = $locale['weekdays_short'];
- break;
- case 'l':
- $options = $locale['weekdays_long'];
- break;
- case 'd':
- $options = $this->_createOptionList(1, 31);
- break;
- case 'M':
- $options = $locale['months_short'];
- array_unshift($options , '');
- unset($options[0]);
- break;
- case 'm':
- $options = $this->_createOptionList(1, 12);
- break;
- case 'F':
- $options = $locale['months_long'];
- array_unshift($options , '');
- unset($options[0]);
- break;
- case 'Y':
- $options = $this->_createOptionList(
- $this->_options['minYear'],
- $this->_options['maxYear'],
- $this->_options['minYear'] > $this->_options['maxYear']? -1: 1
- );
- break;
- case 'y':
- $options = $this->_createOptionList(
- $this->_options['minYear'],
- $this->_options['maxYear'],
- $this->_options['minYear'] > $this->_options['maxYear']? -1: 1
- );
- array_walk($options, create_function('&$v,$k','$v = substr($v,-2);'));
- break;
- case 'h':
- $options = $this->_createOptionList(1, 12);
- break;
- case 'g':
- $options = $this->_createOptionList(1, 12);
- array_walk($options, create_function('&$v,$k', '$v = intval($v);'));
- break;
- case 'H':
- $options = $this->_createOptionList(0, 23);
- break;
- case 'i':
- $options = $this->_createOptionList(0, 59, $this->_options['optionIncrement']['i']);
- break;
- case 's':
- $options = $this->_createOptionList(0, 59, $this->_options['optionIncrement']['s']);
- break;
- case 'a':
- $options = array('am' => 'am', 'pm' => 'pm');
- break;
- case 'A':
- $options = array('AM' => 'AM', 'PM' => 'PM');
- break;
- case 'W':
- $options = $this->_createOptionList(1, 53);
- break;
- case '\\':
- $backslash = true;
- $loadSelect = false;
- break;
- default:
- $separator .= (' ' == $sign? ' ': $sign);
- $loadSelect = false;
- }
-
- if ($loadSelect) {
- if (0 < count($this->_elements)) {
- $this->_separator[] = $separator;
- } else {
- $this->_wrap[0] = $separator;
- }
- $separator = '';
- // Should we add an empty option to the top of the select?
- if (!is_array($this->_options['addEmptyOption']) && $this->_options['addEmptyOption'] ||
- is_array($this->_options['addEmptyOption']) && !empty($this->_options['addEmptyOption'][$sign])) {
-
- // Using '+' array operator to preserve the keys
- if (is_array($this->_options['emptyOptionText']) && !empty($this->_options['emptyOptionText'][$sign])) {
- $options = array($this->_options['emptyOptionValue'] => $this->_options['emptyOptionText'][$sign]) + $options;
- } else {
- $options = array($this->_options['emptyOptionValue'] => $this->_options['emptyOptionText']) + $options;
- }
- }
- $this->_elements[] =& new HTML_QuickForm_select($sign, null, $options, $this->getAttributes());
- }
- }
- }
- $this->_wrap[1] = $separator . ($backslash? '\\': '');
- }
-
- // }}}
- // {{{ _createOptionList()
-
- /**
- * Creates an option list containing the numbers from the start number to the end, inclusive
- *
- * @param int The start number
- * @param int The end number
- * @param int Increment by this value
- * @access private
- * @return array An array of numeric options.
- */
- function _createOptionList($start, $end, $step = 1)
- {
- for ($i = $start, $options = array(); $start > $end? $i >= $end: $i <= $end; $i += $step) {
- $options[$i] = sprintf('%02d', $i);
- }
- return $options;
- }
-
- // }}}
- // {{{ _trimLeadingZeros()
-
- /**
- * Trims leading zeros from the (numeric) string
- *
- * @param string A numeric string, possibly with leading zeros
- * @return string String with leading zeros removed
- */
- function _trimLeadingZeros($str)
- {
- if (0 == strcmp($str, $this->_options['emptyOptionValue'])) {
- return $str;
- }
- $trimmed = ltrim($str, '0');
- return strlen($trimmed)? $trimmed: '0';
- }
-
- // }}}
- // {{{ setValue()
-
- function setValue($value)
- {
- if (empty($value)) {
- $value = array();
- } elseif (is_scalar($value)) {
- if (!is_numeric($value)) {
- $value = strtotime($value);
- }
- // might be a unix epoch, then we fill all possible values
- $arr = explode('-', date('w-j-n-Y-g-G-i-s-a-A-W', (int)$value));
- $value = array(
- 'D' => $arr[0],
- 'l' => $arr[0],
- 'd' => $arr[1],
- 'M' => $arr[2],
- 'm' => $arr[2],
- 'F' => $arr[2],
- 'Y' => $arr[3],
- 'y' => $arr[3],
- 'h' => $arr[4],
- 'g' => $arr[4],
- 'H' => $arr[5],
- 'i' => $this->_trimLeadingZeros($arr[6]),
- 's' => $this->_trimLeadingZeros($arr[7]),
- 'a' => $arr[8],
- 'A' => $arr[9],
- 'W' => $this->_trimLeadingZeros($arr[10])
- );
- } else {
- $value = array_map(array($this, '_trimLeadingZeros'), $value);
- }
- parent::setValue($value);
- }
-
- // }}}
- // {{{ toHtml()
-
- function toHtml()
- {
- include_once('HTML/QuickForm/Renderer/Default.php');
- $renderer =& new HTML_QuickForm_Renderer_Default();
- $renderer->setElementTemplate('{element}');
- parent::accept($renderer);
- return $this->_wrap[0] . $renderer->toHtml() . $this->_wrap[1];
- }
-
- // }}}
- // {{{ accept()
-
- function accept(&$renderer, $required = false, $error = null)
- {
- $renderer->renderElement($this, $required, $error);
- }
-
- // }}}
- // {{{ onQuickFormEvent()
-
- function onQuickFormEvent($event, $arg, &$caller)
- {
- if ('updateValue' == $event) {
- // we need to call setValue(), 'cause the default/constant value
- // may be in fact a timestamp, not an array
- return HTML_QuickForm_element::onQuickFormEvent($event, $arg, $caller);
- } else {
- return parent::onQuickFormEvent($event, $arg, $caller);
- }
- }
-
- // }}}
-}
-?>
\ No newline at end of file
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Base class for form elements
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Alexey Borzov <avb@php.net>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Base class for all HTML classes
- */
-require_once 'HTML/Common.php';
-/**
- * Static utility methods
- */
-require_once 'HTML/QuickForm/utils.php';
-
-/**
- * Base class for form elements
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Alexey Borzov <avb@php.net>
- * @version Release: 3.2.16
- * @since 1.0
- * @abstract
- */
-class HTML_QuickForm_element extends HTML_Common
-{
- // {{{ properties
-
- /**
- * Label of the field
- * @var string
- * @since 1.3
- * @access private
- */
- var $_label = '';
-
- /**
- * Form element type
- * @var string
- * @since 1.0
- * @access private
- */
- var $_type = '';
-
- /**
- * Flag to tell if element is frozen
- * @var boolean
- * @since 1.0
- * @access private
- */
- var $_flagFrozen = false;
-
- /**
- * Does the element support persistant data when frozen
- * @var boolean
- * @since 1.3
- * @access private
- */
- var $_persistantFreeze = false;
-
- // }}}
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string Name of the element
- * @param mixed Label(s) for the element
- * @param mixed Associative array of tag attributes or HTML attributes name="value" pairs
- * @since 1.0
- * @access public
- * @return void
- */
- function HTML_QuickForm_element($elementName=null, $elementLabel=null, $attributes=null)
- {
- HTML_Common::HTML_Common($attributes);
- if (isset($elementName)) {
- $this->setName($elementName);
- }
- if (isset($elementLabel)) {
- $this->setLabel($elementLabel);
- }
- } //end constructor
-
- // }}}
- // {{{ apiVersion()
-
- /**
- * Returns the current API version
- *
- * @since 1.0
- * @access public
- * @return float
- */
- function apiVersion()
- {
- return 3.2;
- } // end func apiVersion
-
- // }}}
- // {{{ getType()
-
- /**
- * Returns element type
- *
- * @since 1.0
- * @access public
- * @return string
- */
- function getType()
- {
- return $this->_type;
- } // end func getType
-
- // }}}
- // {{{ setName()
-
- /**
- * Sets the input field name
- *
- * @param string $name Input field name attribute
- * @since 1.0
- * @access public
- * @return void
- */
- function setName($name)
- {
- // interface method
- } //end func setName
-
- // }}}
- // {{{ getName()
-
- /**
- * Returns the element name
- *
- * @since 1.0
- * @access public
- * @return string
- */
- function getName()
- {
- // interface method
- } //end func getName
-
- // }}}
- // {{{ setValue()
-
- /**
- * Sets the value of the form element
- *
- * @param string $value Default value of the form element
- * @since 1.0
- * @access public
- * @return void
- */
- function setValue($value)
- {
- // interface
- } // end func setValue
-
- // }}}
- // {{{ getValue()
-
- /**
- * Returns the value of the form element
- *
- * @since 1.0
- * @access public
- * @return mixed
- */
- function getValue()
- {
- // interface
- return null;
- } // end func getValue
-
- // }}}
- // {{{ freeze()
-
- /**
- * Freeze the element so that only its value is returned
- *
- * @access public
- * @return void
- */
- function freeze()
- {
- $this->_flagFrozen = true;
- } //end func freeze
-
- // }}}
- // {{{ unfreeze()
-
- /**
- * Unfreezes the element so that it becomes editable
- *
- * @access public
- * @return void
- * @since 3.2.4
- */
- function unfreeze()
- {
- $this->_flagFrozen = false;
- }
-
- // }}}
- // {{{ getFrozenHtml()
-
- /**
- * Returns the value of field without HTML tags
- *
- * @since 1.0
- * @access public
- * @return string
- */
- function getFrozenHtml()
- {
- $value = $this->getValue();
- return (strlen($value)? htmlspecialchars($value): ' ') .
- $this->_getPersistantData();
- } //end func getFrozenHtml
-
- // }}}
- // {{{ _getPersistantData()
-
- /**
- * Used by getFrozenHtml() to pass the element's value if _persistantFreeze is on
- *
- * @access private
- * @return string
- */
- function _getPersistantData()
- {
- if (!$this->_persistantFreeze) {
- return '';
- } else {
- $id = $this->getAttribute('id');
- return '<input' . $this->_getAttrString(array(
- 'type' => 'hidden',
- 'name' => $this->getName(),
- 'value' => $this->getValue()
- ) + (isset($id)? array('id' => $id): array())) . ' />';
- }
- }
-
- // }}}
- // {{{ isFrozen()
-
- /**
- * Returns whether or not the element is frozen
- *
- * @since 1.3
- * @access public
- * @return bool
- */
- function isFrozen()
- {
- return $this->_flagFrozen;
- } // end func isFrozen
-
- // }}}
- // {{{ setPersistantFreeze()
-
- /**
- * Sets wether an element value should be kept in an hidden field
- * when the element is frozen or not
- *
- * @param bool $persistant True if persistant value
- * @since 2.0
- * @access public
- * @return void
- */
- function setPersistantFreeze($persistant=false)
- {
- $this->_persistantFreeze = $persistant;
- } //end func setPersistantFreeze
-
- // }}}
- // {{{ setLabel()
-
- /**
- * Sets display text for the element
- *
- * @param string $label Display text for the element
- * @since 1.3
- * @access public
- * @return void
- */
- function setLabel($label)
- {
- $this->_label = $label;
- } //end func setLabel
-
- // }}}
- // {{{ getLabel()
-
- /**
- * Returns display text for the element
- *
- * @since 1.3
- * @access public
- * @return string
- */
- function getLabel()
- {
- return $this->_label;
- } //end func getLabel
-
- // }}}
- // {{{ _findValue()
-
- /**
- * Tries to find the element value from the values array
- *
- * @since 2.7
- * @access private
- * @return mixed
- */
- function _findValue(&$values)
- {
- if (empty($values)) {
- return null;
- }
- $elementName = $this->getName();
- if (isset($values[$elementName])) {
- return $values[$elementName];
- } elseif (strpos($elementName, '[')) {
-
- $keys = str_replace(
- array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"),
- $elementName
- );
- $arrayKeys = explode("']['", $keys);
- return HTML_QuickForm_utils::recursiveValue($values, $arrayKeys);
-
- } else {
- return null;
- }
- } //end func _findValue
-
- // }}}
- // {{{ onQuickFormEvent()
-
- /**
- * Called by HTML_QuickForm whenever form event is made on this element
- *
- * @param string $event Name of event
- * @param mixed $arg event arguments
- * @param object &$caller calling object
- * @since 1.0
- * @access public
- * @return void
- */
- function onQuickFormEvent($event, $arg, &$caller)
- {
- switch ($event) {
- case 'createElement':
- $className = get_class($this);
- $this->$className($arg[0], $arg[1], $arg[2], $arg[3], $arg[4]);
- break;
- case 'addElement':
- $this->onQuickFormEvent('createElement', $arg, $caller);
- $this->onQuickFormEvent('updateValue', null, $caller);
- break;
- case 'updateValue':
- // constant values override both default and submitted ones
- // default values are overriden by submitted
- $value = $this->_findValue($caller->_constantValues);
- if (null === $value) {
- $value = $this->_findValue($caller->_submitValues);
- if (null === $value) {
- $value = $this->_findValue($caller->_defaultValues);
- }
- }
- if (null !== $value) {
- $this->setValue($value);
- }
- break;
- case 'setGroupValue':
- $this->setValue($arg);
- }
- return true;
- } // end func onQuickFormEvent
-
- // }}}
- // {{{ accept()
-
- /**
- * Accepts a renderer
- *
- * @param HTML_QuickForm_Renderer renderer object
- * @param bool Whether an element is required
- * @param string An error message associated with an element
- * @access public
- * @return void
- */
- function accept(&$renderer, $required=false, $error=null)
- {
- $renderer->renderElement($this, $required, $error);
- } // end func accept
-
- // }}}
- // {{{ _generateId()
-
- /**
- * Automatically generates and assigns an 'id' attribute for the element.
- *
- * Currently used to ensure that labels work on radio buttons and
- * checkboxes. Per idea of Alexander Radivanovich.
- *
- * @access private
- * @return void
- */
- function _generateId()
- {
- static $idx = 1;
-
- if (!$this->getAttribute('id')) {
- $this->updateAttributes(array('id' => 'qf_' . substr(md5(microtime() . $idx++), 0, 6)));
- }
- } // end func _generateId
-
- // }}}
- // {{{ exportValue()
-
- /**
- * Returns a 'safe' element's value
- *
- * @param array array of submitted values to search
- * @param bool whether to return the value as associative array
- * @access public
- * @return mixed
- */
- function exportValue(&$submitValues, $assoc = false)
- {
- $value = $this->_findValue($submitValues);
- if (null === $value) {
- $value = $this->getValue();
- }
- return $this->_prepareValue($value, $assoc);
- }
-
- // }}}
- // {{{ _prepareValue()
-
- /**
- * Used by exportValue() to prepare the value for returning
- *
- * @param mixed the value found in exportValue()
- * @param bool whether to return the value as associative array
- * @access private
- * @return mixed
- */
- function _prepareValue($value, $assoc)
- {
- if (null === $value) {
- return null;
- } elseif (!$assoc) {
- return $value;
- } else {
- $name = $this->getName();
- if (!strpos($name, '[')) {
- return array($name => $value);
- } else {
-
- $keys = str_replace(
- array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"),
- $name
- );
- $keysArray = explode("']['", $keys);
- return HTML_QuickForm_utils::recursiveBuild($keysArray, $value);
- }
- }
- }
-
- // }}}
-} // end class HTML_QuickForm_element
-?>
\ No newline at end of file
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * HTML class for a file upload field
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Alexey Borzov <avb@php.net>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Base class for <input /> form elements
- */
-require_once 'HTML/QuickForm/input.php';
-
-// register file-related rules
-if (class_exists('HTML_QuickForm')) {
- HTML_QuickForm::registerRule('uploadedfile', 'callback', '_ruleIsUploadedFile', 'HTML_QuickForm_file');
- HTML_QuickForm::registerRule('maxfilesize', 'callback', '_ruleCheckMaxFileSize', 'HTML_QuickForm_file');
- HTML_QuickForm::registerRule('mimetype', 'callback', '_ruleCheckMimeType', 'HTML_QuickForm_file');
- HTML_QuickForm::registerRule('filename', 'callback', '_ruleCheckFileName', 'HTML_QuickForm_file');
-}
-
-/**
- * HTML class for a file upload field
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Alexey Borzov <avb@php.net>
- * @version Release: 3.2.16
- * @since 1.0
- */
-class HTML_QuickForm_file extends HTML_QuickForm_input
-{
- // {{{ properties
-
- /**
- * Uploaded file data, from $_FILES
- * @var array
- */
- var $_value = null;
-
- // }}}
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string Input field name attribute
- * @param string Input field label
- * @param mixed (optional)Either a typical HTML attribute string
- * or an associative array
- * @since 1.0
- * @access public
- */
- function HTML_QuickForm_file($elementName=null, $elementLabel=null, $attributes=null)
- {
- HTML_QuickForm_input::HTML_QuickForm_input($elementName, $elementLabel, $attributes);
- $this->setType('file');
- } //end constructor
-
- // }}}
- // {{{ setSize()
-
- /**
- * Sets size of file element
- *
- * @param int Size of file element
- * @since 1.0
- * @access public
- */
- function setSize($size)
- {
- $this->updateAttributes(array('size' => $size));
- } //end func setSize
-
- // }}}
- // {{{ getSize()
-
- /**
- * Returns size of file element
- *
- * @since 1.0
- * @access public
- * @return int
- */
- function getSize()
- {
- return $this->getAttribute('size');
- } //end func getSize
-
- // }}}
- // {{{ freeze()
-
- /**
- * Freeze the element so that only its value is returned
- *
- * @access public
- * @return bool
- */
- function freeze()
- {
- return false;
- } //end func freeze
-
- // }}}
- // {{{ setValue()
-
- /**
- * Sets value for file element.
- *
- * Actually this does nothing. The function is defined here to override
- * HTML_Quickform_input's behaviour of setting the 'value' attribute. As
- * no sane user-agent uses <input type="file">'s value for anything
- * (because of security implications) we implement file's value as a
- * read-only property with a special meaning.
- *
- * @param mixed Value for file element
- * @since 3.0
- * @access public
- */
- function setValue($value)
- {
- return null;
- } //end func setValue
-
- // }}}
- // {{{ getValue()
-
- /**
- * Returns information about the uploaded file
- *
- * @since 3.0
- * @access public
- * @return array
- */
- function getValue()
- {
- return $this->_value;
- } // end func getValue
-
- // }}}
- // {{{ onQuickFormEvent()
-
- /**
- * Called by HTML_QuickForm whenever form event is made on this element
- *
- * @param string Name of event
- * @param mixed event arguments
- * @param object calling object
- * @since 1.0
- * @access public
- * @return bool
- */
- function onQuickFormEvent($event, $arg, &$caller)
- {
- switch ($event) {
- case 'updateValue':
- if ($caller->getAttribute('method') == 'get') {
- return PEAR::raiseError('Cannot add a file upload field to a GET method form');
- }
- $this->_value = $this->_findValue();
- $caller->updateAttributes(array('enctype' => 'multipart/form-data'));
- $caller->setMaxFileSize();
- break;
- case 'addElement':
- $this->onQuickFormEvent('createElement', $arg, $caller);
- return $this->onQuickFormEvent('updateValue', null, $caller);
- break;
- case 'createElement':
- $className = get_class($this);
- $this->$className($arg[0], $arg[1], $arg[2]);
- break;
- }
- return true;
- } // end func onQuickFormEvent
-
- // }}}
- // {{{ moveUploadedFile()
-
- /**
- * Moves an uploaded file into the destination
- *
- * @param string Destination directory path
- * @param string New file name
- * @access public
- * @return bool Whether the file was moved successfully
- */
- function moveUploadedFile($dest, $fileName = '')
- {
- if ($dest != '' && substr($dest, -1) != '/') {
- $dest .= '/';
- }
- $fileName = ($fileName != '') ? $fileName : basename($this->_value['name']);
- return move_uploaded_file($this->_value['tmp_name'], $dest . $fileName);
- } // end func moveUploadedFile
-
- // }}}
- // {{{ isUploadedFile()
-
- /**
- * Checks if the element contains an uploaded file
- *
- * @access public
- * @return bool true if file has been uploaded, false otherwise
- */
- function isUploadedFile()
- {
- return $this->_ruleIsUploadedFile($this->_value);
- } // end func isUploadedFile
-
- // }}}
- // {{{ _ruleIsUploadedFile()
-
- /**
- * Checks if the given element contains an uploaded file
- *
- * @param array Uploaded file info (from $_FILES)
- * @access private
- * @return bool true if file has been uploaded, false otherwise
- */
- function _ruleIsUploadedFile($elementValue)
- {
- if ((isset($elementValue['error']) && $elementValue['error'] == 0) ||
- (!empty($elementValue['tmp_name']) && $elementValue['tmp_name'] != 'none')) {
- return is_uploaded_file($elementValue['tmp_name']);
- } else {
- return false;
- }
- } // end func _ruleIsUploadedFile
-
- // }}}
- // {{{ _ruleCheckMaxFileSize()
-
- /**
- * Checks that the file does not exceed the max file size
- *
- * @param array Uploaded file info (from $_FILES)
- * @param int Max file size
- * @access private
- * @return bool true if filesize is lower than maxsize, false otherwise
- */
- function _ruleCheckMaxFileSize($elementValue, $maxSize)
- {
- if (!empty($elementValue['error']) &&
- (UPLOAD_ERR_FORM_SIZE == $elementValue['error'] || UPLOAD_ERR_INI_SIZE == $elementValue['error'])) {
- return false;
- }
- if (!HTML_QuickForm_file::_ruleIsUploadedFile($elementValue)) {
- return true;
- }
- return ($maxSize >= @filesize($elementValue['tmp_name']));
- } // end func _ruleCheckMaxFileSize
-
- // }}}
- // {{{ _ruleCheckMimeType()
-
- /**
- * Checks if the given element contains an uploaded file of the right mime type
- *
- * @param array Uploaded file info (from $_FILES)
- * @param mixed Mime Type (can be an array of allowed types)
- * @access private
- * @return bool true if mimetype is correct, false otherwise
- */
- function _ruleCheckMimeType($elementValue, $mimeType)
- {
- if (!HTML_QuickForm_file::_ruleIsUploadedFile($elementValue)) {
- return true;
- }
- if (is_array($mimeType)) {
- return in_array($elementValue['type'], $mimeType);
- }
- return $elementValue['type'] == $mimeType;
- } // end func _ruleCheckMimeType
-
- // }}}
- // {{{ _ruleCheckFileName()
-
- /**
- * Checks if the given element contains an uploaded file of the filename regex
- *
- * @param array Uploaded file info (from $_FILES)
- * @param string Regular expression
- * @access private
- * @return bool true if name matches regex, false otherwise
- */
- function _ruleCheckFileName($elementValue, $regex)
- {
- if (!HTML_QuickForm_file::_ruleIsUploadedFile($elementValue)) {
- return true;
- }
- return (bool)preg_match($regex, $elementValue['name']);
- } // end func _ruleCheckFileName
-
- // }}}
- // {{{ _findValue()
-
- /**
- * Tries to find the element value from the values array
- *
- * Needs to be redefined here as $_FILES is populated differently from
- * other arrays when element name is of the form foo[bar]
- *
- * @param bool $sc1 unused, for signature compatibility
- *
- * @access private
- * @return mixed
- */
- function _findValue(&$sc1 = null)
- {
- if (empty($_FILES)) {
- return null;
- }
- $elementName = $this->getName();
- if (isset($_FILES[$elementName])) {
- return $_FILES[$elementName];
- } elseif (false !== ($pos = strpos($elementName, '['))) {
- $base = str_replace(
- array('\\', '\''), array('\\\\', '\\\''),
- substr($elementName, 0, $pos)
- );
- $idx = "['" . str_replace(
- array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"),
- substr($elementName, $pos + 1, -1)
- ) . "']";
- $props = array('name', 'type', 'size', 'tmp_name', 'error');
- $code = "if (!isset(\$_FILES['{$base}']['name']{$idx})) {\n" .
- " return null;\n" .
- "} else {\n" .
- " \$value = array();\n";
- foreach ($props as $prop) {
- $code .= " \$value['{$prop}'] = \$_FILES['{$base}']['{$prop}']{$idx};\n";
- }
- return eval($code . " return \$value;\n}\n");
- } else {
- return null;
- }
- }
-
- // }}}
-} // end class HTML_QuickForm_file
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * HTML class for a form element group
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Alexey Borzov <avb@php.net>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Base class for form elements
- */
-require_once 'HTML/QuickForm/element.php';
-
-/**
- * HTML class for a form element group
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Alexey Borzov <avb@php.net>
- * @version Release: 3.2.16
- * @since 1.0
- */
-class HTML_QuickForm_group extends HTML_QuickForm_element
-{
- // {{{ properties
-
- /**
- * Name of the element
- * @var string
- * @since 1.0
- * @access private
- */
- var $_name = '';
-
- /**
- * Array of grouped elements
- * @var array
- * @since 1.0
- * @access private
- */
- var $_elements = array();
-
- /**
- * String to separate elements
- * @var mixed
- * @since 2.5
- * @access private
- */
- var $_separator = null;
-
- /**
- * Required elements in this group
- * @var array
- * @since 2.5
- * @access private
- */
- var $_required = array();
-
- /**
- * Whether to change elements' names to $groupName[$elementName] or leave them as is
- * @var bool
- * @since 3.0
- * @access private
- */
- var $_appendName = true;
-
- // }}}
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string $elementName (optional)Group name
- * @param array $elementLabel (optional)Group label
- * @param array $elements (optional)Group elements
- * @param mixed $separator (optional)Use a string for one separator,
- * use an array to alternate the separators.
- * @param bool $appendName (optional)whether to change elements' names to
- * the form $groupName[$elementName] or leave
- * them as is.
- * @since 1.0
- * @access public
- * @return void
- */
- function HTML_QuickForm_group($elementName=null, $elementLabel=null, $elements=null, $separator=null, $appendName = true)
- {
- $this->HTML_QuickForm_element($elementName, $elementLabel);
- $this->_type = 'group';
- if (isset($elements) && is_array($elements)) {
- $this->setElements($elements);
- }
- if (isset($separator)) {
- $this->_separator = $separator;
- }
- if (isset($appendName)) {
- $this->_appendName = $appendName;
- }
- } //end constructor
-
- // }}}
- // {{{ setName()
-
- /**
- * Sets the group name
- *
- * @param string $name Group name
- * @since 1.0
- * @access public
- * @return void
- */
- function setName($name)
- {
- $this->_name = $name;
- } //end func setName
-
- // }}}
- // {{{ getName()
-
- /**
- * Returns the group name
- *
- * @since 1.0
- * @access public
- * @return string
- */
- function getName()
- {
- return $this->_name;
- } //end func getName
-
- // }}}
- // {{{ setValue()
-
- /**
- * Sets values for group's elements
- *
- * @param mixed Values for group's elements
- * @since 1.0
- * @access public
- * @return void
- */
- function setValue($value)
- {
- $this->_createElementsIfNotExist();
- foreach (array_keys($this->_elements) as $key) {
- if (!$this->_appendName) {
- $v = $this->_elements[$key]->_findValue($value);
- if (null !== $v) {
- $this->_elements[$key]->onQuickFormEvent('setGroupValue', $v, $this);
- }
-
- } else {
- $elementName = $this->_elements[$key]->getName();
- $index = strlen($elementName) ? $elementName : $key;
- if (is_array($value)) {
- if (isset($value[$index])) {
- $this->_elements[$key]->onQuickFormEvent('setGroupValue', $value[$index], $this);
- }
- } elseif (isset($value)) {
- $this->_elements[$key]->onQuickFormEvent('setGroupValue', $value, $this);
- }
- }
- }
- } //end func setValue
-
- // }}}
- // {{{ getValue()
-
- /**
- * Returns the value of the group
- *
- * @since 1.0
- * @access public
- * @return mixed
- */
- function getValue()
- {
- $value = null;
- foreach (array_keys($this->_elements) as $key) {
- $element =& $this->_elements[$key];
- switch ($element->getType()) {
- case 'radio':
- $v = $element->getChecked()? $element->getValue(): null;
- break;
- case 'checkbox':
- $v = $element->getChecked()? true: null;
- break;
- default:
- $v = $element->getValue();
- }
- if (null !== $v) {
- $elementName = $element->getName();
- if (is_null($elementName)) {
- $value = $v;
- } else {
- if (!is_array($value)) {
- $value = is_null($value)? array(): array($value);
- }
- if ('' === $elementName) {
- $value[] = $v;
- } else {
- $value[$elementName] = $v;
- }
- }
- }
- }
- return $value;
- } // end func getValue
-
- // }}}
- // {{{ setElements()
-
- /**
- * Sets the grouped elements
- *
- * @param array $elements Array of elements
- * @since 1.1
- * @access public
- * @return void
- */
- function setElements($elements)
- {
- $this->_elements = array_values($elements);
- if ($this->_flagFrozen) {
- $this->freeze();
- }
- } // end func setElements
-
- // }}}
- // {{{ getElements()
-
- /**
- * Gets the grouped elements
- *
- * @since 2.4
- * @access public
- * @return array
- */
- function &getElements()
- {
- $this->_createElementsIfNotExist();
- return $this->_elements;
- } // end func getElements
-
- // }}}
- // {{{ getGroupType()
-
- /**
- * Gets the group type based on its elements
- * Will return 'mixed' if elements contained in the group
- * are of different types.
- *
- * @access public
- * @return string group elements type
- */
- function getGroupType()
- {
- $this->_createElementsIfNotExist();
- $prevType = '';
- foreach (array_keys($this->_elements) as $key) {
- $type = $this->_elements[$key]->getType();
- if ($type != $prevType && $prevType != '') {
- return 'mixed';
- }
- $prevType = $type;
- }
- return $type;
- } // end func getGroupType
-
- // }}}
- // {{{ toHtml()
-
- /**
- * Returns Html for the group
- *
- * @since 1.0
- * @access public
- * @return string
- */
- function toHtml()
- {
- include_once('HTML/QuickForm/Renderer/Default.php');
- $renderer = new HTML_QuickForm_Renderer_Default();
- $renderer->setElementTemplate('{element}');
- $this->accept($renderer);
- return $renderer->toHtml();
- } //end func toHtml
-
- // }}}
- // {{{ getElementName()
-
- /**
- * Returns the element name inside the group such as found in the html form
- *
- * @param mixed $index Element name or element index in the group
- * @since 3.0
- * @access public
- * @return mixed string with element name, false if not found
- */
- function getElementName($index)
- {
- $this->_createElementsIfNotExist();
- $elementName = false;
- if (is_int($index) && isset($this->_elements[$index])) {
- $elementName = $this->_elements[$index]->getName();
- if (isset($elementName) && $elementName == '') {
- $elementName = $index;
- }
- if ($this->_appendName) {
- if (is_null($elementName)) {
- $elementName = $this->getName();
- } else {
- $elementName = $this->getName().'['.$elementName.']';
- }
- }
-
- } elseif (is_string($index)) {
- foreach (array_keys($this->_elements) as $key) {
- $elementName = $this->_elements[$key]->getName();
- if ($index == $elementName) {
- if ($this->_appendName) {
- $elementName = $this->getName().'['.$elementName.']';
- }
- break;
- } elseif ($this->_appendName && $this->getName().'['.$elementName.']' == $index) {
- break;
- }
- }
- }
- return $elementName;
- } //end func getElementName
-
- // }}}
- // {{{ getFrozenHtml()
-
- /**
- * Returns the value of field without HTML tags
- *
- * @since 1.3
- * @access public
- * @return string
- */
- function getFrozenHtml()
- {
- $flags = array();
- $this->_createElementsIfNotExist();
- foreach (array_keys($this->_elements) as $key) {
- if (false === ($flags[$key] = $this->_elements[$key]->isFrozen())) {
- $this->_elements[$key]->freeze();
- }
- }
- $html = $this->toHtml();
- foreach (array_keys($this->_elements) as $key) {
- if (!$flags[$key]) {
- $this->_elements[$key]->unfreeze();
- }
- }
- return $html;
- } //end func getFrozenHtml
-
- // }}}
- // {{{ onQuickFormEvent()
-
- /**
- * Called by HTML_QuickForm whenever form event is made on this element
- *
- * @param string $event Name of event
- * @param mixed $arg event arguments
- * @param object &$caller calling object
- * @since 1.0
- * @access public
- * @return void
- */
- function onQuickFormEvent($event, $arg, &$caller)
- {
- switch ($event) {
- case 'updateValue':
- $this->_createElementsIfNotExist();
- foreach (array_keys($this->_elements) as $key) {
- if ($this->_appendName) {
- $elementName = $this->_elements[$key]->getName();
- if (is_null($elementName)) {
- $this->_elements[$key]->setName($this->getName());
- } elseif ('' === $elementName) {
- $this->_elements[$key]->setName($this->getName() . '[' . $key . ']');
- } else {
- $this->_elements[$key]->setName($this->getName() . '[' . $elementName . ']');
- }
- }
- $this->_elements[$key]->onQuickFormEvent('updateValue', $arg, $caller);
- if ($this->_appendName) {
- $this->_elements[$key]->setName($elementName);
- }
- }
- break;
-
- default:
- parent::onQuickFormEvent($event, $arg, $caller);
- }
- return true;
- } // end func onQuickFormEvent
-
- // }}}
- // {{{ accept()
-
- /**
- * Accepts a renderer
- *
- * @param HTML_QuickForm_Renderer renderer object
- * @param bool Whether a group is required
- * @param string An error message associated with a group
- * @access public
- * @return void
- */
- function accept(&$renderer, $required = false, $error = null)
- {
- $this->_createElementsIfNotExist();
- $renderer->startGroup($this, $required, $error);
- $name = $this->getName();
- foreach (array_keys($this->_elements) as $key) {
- $element =& $this->_elements[$key];
-
- if ($this->_appendName) {
- $elementName = $element->getName();
- if (isset($elementName)) {
- $element->setName($name . '['. (strlen($elementName)? $elementName: $key) .']');
- } else {
- $element->setName($name);
- }
- }
-
- $required = !$element->isFrozen() && in_array($element->getName(), $this->_required);
-
- $element->accept($renderer, $required);
-
- // restore the element's name
- if ($this->_appendName) {
- $element->setName($elementName);
- }
- }
- $renderer->finishGroup($this);
- } // end func accept
-
- // }}}
- // {{{ exportValue()
-
- /**
- * As usual, to get the group's value we access its elements and call
- * their exportValue() methods
- */
- function exportValue(&$submitValues, $assoc = false)
- {
- $value = null;
- foreach (array_keys($this->_elements) as $key) {
- $elementName = $this->_elements[$key]->getName();
- if ($this->_appendName) {
- if (is_null($elementName)) {
- $this->_elements[$key]->setName($this->getName());
- } elseif ('' === $elementName) {
- $this->_elements[$key]->setName($this->getName() . '[' . $key . ']');
- } else {
- $this->_elements[$key]->setName($this->getName() . '[' . $elementName . ']');
- }
- }
- $v = $this->_elements[$key]->exportValue($submitValues, $assoc);
- if ($this->_appendName) {
- $this->_elements[$key]->setName($elementName);
- }
- if (null !== $v) {
- // Make $value an array, we will use it like one
- if (null === $value) {
- $value = array();
- }
- if ($assoc) {
- // just like HTML_QuickForm::exportValues()
- $value = HTML_QuickForm::arrayMerge($value, $v);
- } else {
- // just like getValue(), but should work OK every time here
- if (is_null($elementName)) {
- $value = $v;
- } elseif ('' === $elementName) {
- $value[] = $v;
- } else {
- $value[$elementName] = $v;
- }
- }
- }
- }
- // do not pass the value through _prepareValue, we took care of this already
- return $value;
- }
-
- // }}}
- // {{{ _createElements()
-
- /**
- * Creates the group's elements.
- *
- * This should be overriden by child classes that need to create their
- * elements. The method will be called automatically when needed, calling
- * it from the constructor is discouraged as the constructor is usually
- * called _twice_ on element creation, first time with _no_ parameters.
- *
- * @access private
- * @abstract
- */
- function _createElements()
- {
- // abstract
- }
-
- // }}}
- // {{{ _createElementsIfNotExist()
-
- /**
- * A wrapper around _createElements()
- *
- * This method calls _createElements() if the group's _elements array
- * is empty. It also performs some updates, e.g. freezes the created
- * elements if the group is already frozen.
- *
- * @access private
- */
- function _createElementsIfNotExist()
- {
- if (empty($this->_elements)) {
- $this->_createElements();
- if ($this->_flagFrozen) {
- $this->freeze();
- }
- }
- }
-
- // }}}
- // {{{ freeze()
-
- function freeze()
- {
- parent::freeze();
- foreach (array_keys($this->_elements) as $key) {
- $this->_elements[$key]->freeze();
- }
- }
-
- // }}}
- // {{{ unfreeze()
-
- function unfreeze()
- {
- parent::unfreeze();
- foreach (array_keys($this->_elements) as $key) {
- $this->_elements[$key]->unfreeze();
- }
- }
-
- // }}}
- // {{{ setPersistantFreeze()
-
- function setPersistantFreeze($persistant = false)
- {
- parent::setPersistantFreeze($persistant);
- foreach (array_keys($this->_elements) as $key) {
- $this->_elements[$key]->setPersistantFreeze($persistant);
- }
- }
-
- // }}}
-} //end class HTML_QuickForm_group
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * A pseudo-element used for adding headers to form
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Alexey Borzov <avb@php.net>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * HTML class for static data
- */
-require_once 'HTML/QuickForm/static.php';
-
-/**
- * A pseudo-element used for adding headers to form
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Alexey Borzov <avb@php.net>
- * @version Release: 3.2.16
- * @since 3.0
- */
-class HTML_QuickForm_header extends HTML_QuickForm_static
-{
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string $elementName Header name
- * @param string $text Header text
- * @access public
- * @return void
- */
- function HTML_QuickForm_header($elementName = null, $text = null)
- {
- $this->HTML_QuickForm_static($elementName, null, $text);
- $this->_type = 'header';
- }
-
- // }}}
- // {{{ accept()
-
- /**
- * Accepts a renderer
- *
- * @param HTML_QuickForm_Renderer renderer object
- * @param bool $sc1 unused, for signature compatibility
- * @param bool $sc2 unused, for signature compatibility
- * @access public
- * @return void
- */
- function accept(&$renderer, $sc1 = false, $sc2 = null)
- {
- $renderer->renderHeader($this);
- } // end func accept
-
- // }}}
-
-} //end class HTML_QuickForm_header
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * HTML class for a hidden type element
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Base class for <input /> form elements
- */
-require_once 'HTML/QuickForm/input.php';
-
-/**
- * HTML class for a hidden type element
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @version Release: 3.2.16
- * @since 1.0
- */
-class HTML_QuickForm_hidden extends HTML_QuickForm_input
-{
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string $elementName (optional)Input field name attribute
- * @param string $value (optional)Input field value
- * @param mixed $attributes (optional)Either a typical HTML attribute string
- * or an associative array
- * @since 1.0
- * @access public
- * @return void
- */
- function HTML_QuickForm_hidden($elementName=null, $value='', $attributes=null)
- {
- HTML_QuickForm_input::HTML_QuickForm_input($elementName, null, $attributes);
- $this->setType('hidden');
- $this->setValue($value);
- } //end constructor
-
- // }}}
- // {{{ freeze()
-
- /**
- * Freeze the element so that only its value is returned
- *
- * @access public
- * @return void
- */
- function freeze()
- {
- return false;
- } //end func freeze
-
- // }}}
- // {{{ accept()
-
- /**
- * Accepts a renderer
- *
- * @param HTML_QuickForm_Renderer renderer object
- * @param bool $sc1 unused, for signature compatibility
- * @param bool $sc2 unused, for signature compatibility
- * @access public
- * @return void
- */
- function accept(&$renderer, $sc1 = false, $sc2 = null)
- {
- $renderer->renderHidden($this);
- } // end func accept
-
- // }}}
-
-} //end class HTML_QuickForm_hidden
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Hidden select pseudo-element
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Isaac Shepard <ishepard@bsiweb.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Class for <select></select> elements
- */
-require_once 'HTML/QuickForm/select.php';
-
-/**
- * Hidden select pseudo-element
- *
- * This class takes the same arguments as a select element, but instead
- * of creating a select ring it creates hidden elements for all values
- * already selected with setDefault or setConstant. This is useful if
- * you have a select ring that you don't want visible, but you need all
- * selected values to be passed.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Isaac Shepard <ishepard@bsiweb.com>
- * @version Release: 3.2.16
- * @since 2.1
- */
-class HTML_QuickForm_hiddenselect extends HTML_QuickForm_select
-{
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string Select name attribute
- * @param mixed Label(s) for the select (not used)
- * @param mixed Data to be used to populate options
- * @param mixed Either a typical HTML attribute string or an associative array (not used)
- * @since 1.0
- * @access public
- * @return void
- */
- function HTML_QuickForm_hiddenselect($elementName=null, $elementLabel=null, $options=null, $attributes=null)
- {
- HTML_QuickForm_element::HTML_QuickForm_element($elementName, $elementLabel, $attributes);
- $this->_persistantFreeze = true;
- $this->_type = 'hiddenselect';
- if (isset($options)) {
- $this->load($options);
- }
- } //end constructor
-
- // }}}
- // {{{ toHtml()
-
- /**
- * Returns the SELECT in HTML
- *
- * @since 1.0
- * @access public
- * @return string
- * @throws
- */
- function toHtml()
- {
- if (empty($this->_values)) {
- return '';
- }
-
- $tabs = $this->_getTabs();
- $name = $this->getPrivateName();
- $strHtml = '';
-
- foreach ($this->_values as $key => $val) {
- for ($i = 0, $optCount = count($this->_options); $i < $optCount; $i++) {
- if ($val == $this->_options[$i]['attr']['value']) {
- $strHtml .= $tabs . '<input' . $this->_getAttrString(array(
- 'type' => 'hidden',
- 'name' => $name,
- 'value' => $val
- )) . " />\n" ;
- }
- }
- }
-
- return $strHtml;
- } //end func toHtml
-
- // }}}
- // {{{ accept()
-
- /**
- * This is essentially a hidden element and should be rendered as one
- *
- * @param HTML_QuickForm_Renderer renderer object
- * @param bool $sc1 unused, for signature compatibility
- * @param bool $sc2 unused, for signature compatibility
- */
- function accept(&$renderer, $sc1 = false, $sc2 = null)
- {
- $renderer->renderHidden($this);
- }
-
- // }}}
-} //end class HTML_QuickForm_hiddenselect
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Hierarchical select element
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Herim Vasquez <vasquezh@iro.umontreal.ca>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Alexey Borzov <avb@php.net>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Class for a group of form elements
- */
-require_once 'HTML/QuickForm/group.php';
-/**
- * Class for <select></select> elements
- */
-require_once 'HTML/QuickForm/select.php';
-/**
- * Static utility methods
- */
-require_once 'HTML/QuickForm/utils.php';
-
-/**
- * Hierarchical select element
- *
- * Class to dynamically create two or more HTML Select elements
- * The first select changes the content of the second select and so on.
- * This element is considered as a group. Selects will be named
- * groupName[0], groupName[1], groupName[2]...
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Herim Vasquez <vasquezh@iro.umontreal.ca>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Alexey Borzov <avb@php.net>
- * @version Release: 3.2.16
- * @since 3.1
- */
-class HTML_QuickForm_hierselect extends HTML_QuickForm_group
-{
- // {{{ properties
-
- /**
- * Options for all the select elements
- *
- * @see setOptions()
- * @var array
- * @access private
- */
- var $_options = array();
-
- /**
- * Number of select elements on this group
- *
- * @var int
- * @access private
- */
- var $_nbElements = 0;
-
- /**
- * The javascript used to set and change the options
- *
- * @var string
- * @access private
- */
- var $_js = '';
-
- // }}}
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string $elementName (optional)Input field name attribute
- * @param string $elementLabel (optional)Input field label in form
- * @param mixed $attributes (optional)Either a typical HTML attribute string
- * or an associative array. Date format is passed along the attributes.
- * @param mixed $separator (optional)Use a string for one separator,
- * use an array to alternate the separators.
- * @access public
- * @return void
- */
- function HTML_QuickForm_hierselect($elementName=null, $elementLabel=null, $attributes=null, $separator=null)
- {
- $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes);
- $this->_persistantFreeze = true;
- if (isset($separator)) {
- $this->_separator = $separator;
- }
- $this->_type = 'hierselect';
- $this->_appendName = true;
- } //end constructor
-
- // }}}
- // {{{ setOptions()
-
- /**
- * Initialize the array structure containing the options for each select element.
- * Call the functions that actually do the magic.
- *
- * Format is a bit more complex than for a simple select as we need to know
- * which options are related to the ones in the previous select:
- *
- * Ex:
- * <code>
- * // first select
- * $select1[0] = 'Pop';
- * $select1[1] = 'Classical';
- * $select1[2] = 'Funeral doom';
- *
- * // second select
- * $select2[0][0] = 'Red Hot Chil Peppers';
- * $select2[0][1] = 'The Pixies';
- * $select2[1][0] = 'Wagner';
- * $select2[1][1] = 'Strauss';
- * $select2[2][0] = 'Pantheist';
- * $select2[2][1] = 'Skepticism';
- *
- * // If only need two selects
- * // - and using the deprecated functions
- * $sel =& $form->addElement('hierselect', 'cds', 'Choose CD:');
- * $sel->setMainOptions($select1);
- * $sel->setSecOptions($select2);
- *
- * // - and using the new setOptions function
- * $sel =& $form->addElement('hierselect', 'cds', 'Choose CD:');
- * $sel->setOptions(array($select1, $select2));
- *
- * // If you have a third select with prices for the cds
- * $select3[0][0][0] = '15.00$';
- * $select3[0][0][1] = '17.00$';
- * // etc
- *
- * // You can now use
- * $sel =& $form->addElement('hierselect', 'cds', 'Choose CD:');
- * $sel->setOptions(array($select1, $select2, $select3));
- * </code>
- *
- * @param array $options Array of options defining each element
- * @access public
- * @return void
- */
- function setOptions($options)
- {
- $this->_options = $options;
-
- if (empty($this->_elements)) {
- $this->_nbElements = count($this->_options);
- $this->_createElements();
- } else {
- // setDefaults has probably been called before this function
- // check if all elements have been created
- $totalNbElements = count($this->_options);
- for ($i = $this->_nbElements; $i < $totalNbElements; $i ++) {
- $this->_elements[] =& new HTML_QuickForm_select($i, null, array(), $this->getAttributes());
- $this->_nbElements++;
- }
- }
-
- $this->_setOptions();
- } // end func setMainOptions
-
- // }}}
- // {{{ setMainOptions()
-
- /**
- * Sets the options for the first select element. Deprecated. setOptions() should be used.
- *
- * @param array $array Options for the first select element
- *
- * @access public
- * @deprecated Deprecated since release 3.2.2
- * @return void
- */
- function setMainOptions($array)
- {
- $this->_options[0] = $array;
-
- if (empty($this->_elements)) {
- $this->_nbElements = 2;
- $this->_createElements();
- }
- } // end func setMainOptions
-
- // }}}
- // {{{ setSecOptions()
-
- /**
- * Sets the options for the second select element. Deprecated. setOptions() should be used.
- * The main _options array is initialized and the _setOptions function is called.
- *
- * @param array $array Options for the second select element
- *
- * @access public
- * @deprecated Deprecated since release 3.2.2
- * @return void
- */
- function setSecOptions($array)
- {
- $this->_options[1] = $array;
-
- if (empty($this->_elements)) {
- $this->_nbElements = 2;
- $this->_createElements();
- } else {
- // setDefaults has probably been called before this function
- // check if all elements have been created
- $totalNbElements = 2;
- for ($i = $this->_nbElements; $i < $totalNbElements; $i ++) {
- $this->_elements[] =& new HTML_QuickForm_select($i, null, array(), $this->getAttributes());
- $this->_nbElements++;
- }
- }
-
- $this->_setOptions();
- } // end func setSecOptions
-
- // }}}
- // {{{ _setOptions()
-
- /**
- * Sets the options for each select element
- *
- * @access private
- * @return void
- */
- function _setOptions()
- {
- $arrayKeys = array();
- foreach (array_keys($this->_elements) AS $key) {
- if (isset($this->_options[$key])) {
- if ((empty($arrayKeys)) || HTML_QuickForm_utils::recursiveIsset($this->_options[$key], $arrayKeys)) {
- $array = empty($arrayKeys) ? $this->_options[$key] : HTML_QuickForm_utils::recursiveValue($this->_options[$key], $arrayKeys);
- if (is_array($array)) {
- $select =& $this->_elements[$key];
- $select->_options = array();
- $select->loadArray($array);
-
- $value = is_array($v = $select->getValue()) ? $v[0] : key($array);
- $arrayKeys[] = $value;
- }
- }
- }
- }
- } // end func _setOptions
-
- // }}}
- // {{{ setValue()
-
- /**
- * Sets values for group's elements
- *
- * @param array $value An array of 2 or more values, for the first,
- * the second, the third etc. select
- *
- * @access public
- * @return void
- */
- function setValue($value)
- {
- // fix for bug #6766. Hope this doesn't break anything more
- // after bug #7961. Forgot that _nbElements was used in
- // _createElements() called in several places...
- $this->_nbElements = max($this->_nbElements, count($value));
- parent::setValue($value);
- $this->_setOptions();
- } // end func setValue
-
- // }}}
- // {{{ _createElements()
-
- /**
- * Creates all the elements for the group
- *
- * @access private
- * @return void
- */
- function _createElements()
- {
- for ($i = 0; $i < $this->_nbElements; $i++) {
- $this->_elements[] =& new HTML_QuickForm_select($i, null, array(), $this->getAttributes());
- }
- } // end func _createElements
-
- // }}}
- // {{{ toHtml()
-
- function toHtml()
- {
- $this->_js = '';
- if (!$this->_flagFrozen) {
- // set the onchange attribute for each element except last
- $keys = array_keys($this->_elements);
- $onChange = array();
- for ($i = 0; $i < count($keys) - 1; $i++) {
- $select =& $this->_elements[$keys[$i]];
- $onChange[$i] = $select->getAttribute('onchange');
- $select->updateAttributes(
- array('onchange' => '_hs_swapOptions(this.form, \'' . $this->_escapeString($this->getName()) . '\', ' . $keys[$i] . ');' . $onChange[$i])
- );
- }
-
- // create the js function to call
- if (!defined('HTML_QUICKFORM_HIERSELECT_EXISTS')) {
- $this->_js .= <<<JAVASCRIPT
-function _hs_findOptions(ary, keys)
-{
- if (ary == undefined) {
- return {};
- }
- var key = keys.shift();
- if (!key in ary) {
- return {};
- } else if (0 == keys.length) {
- return ary[key];
- } else {
- return _hs_findOptions(ary[key], keys);
- }
-}
-
-function _hs_findSelect(form, groupName, selectIndex)
-{
- if (groupName+'['+ selectIndex +']' in form) {
- return form[groupName+'['+ selectIndex +']'];
- } else {
- return form[groupName+'['+ selectIndex +'][]'];
- }
-}
-
-function _hs_unescapeEntities(str)
-{
- var div = document.createElement('div');
- div.innerHTML = str;
- return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
-}
-
-function _hs_replaceOptions(ctl, options)
-{
- var j = 0;
- ctl.options.length = 0;
- for (var i = 0; i < options.values.length; i++) {
- ctl.options[i] = new Option(
- (-1 == String(options.texts[i]).indexOf('&'))? options.texts[i]: _hs_unescapeEntities(options.texts[i]),
- options.values[i], false, false
- );
- }
-}
-
-function _hs_setValue(ctl, value)
-{
- var testValue = {};
- if (value instanceof Array) {
- for (var i = 0; i < value.length; i++) {
- testValue[value[i]] = true;
- }
- } else {
- testValue[value] = true;
- }
- for (var i = 0; i < ctl.options.length; i++) {
- if (ctl.options[i].value in testValue) {
- ctl.options[i].selected = true;
- }
- }
-}
-
-function _hs_swapOptions(form, groupName, selectIndex)
-{
- var hsValue = [];
- for (var i = 0; i <= selectIndex; i++) {
- hsValue[i] = _hs_findSelect(form, groupName, i).value;
- }
-
- _hs_replaceOptions(_hs_findSelect(form, groupName, selectIndex + 1),
- _hs_findOptions(_hs_options[groupName][selectIndex], hsValue));
- if (selectIndex + 1 < _hs_options[groupName].length) {
- _hs_swapOptions(form, groupName, selectIndex + 1);
- }
-}
-
-function _hs_onReset(form, groupNames)
-{
- for (var i = 0; i < groupNames.length; i++) {
- try {
- for (var j = 0; j <= _hs_options[groupNames[i]].length; j++) {
- _hs_setValue(_hs_findSelect(form, groupNames[i], j), _hs_defaults[groupNames[i]][j]);
- if (j < _hs_options[groupNames[i]].length) {
- _hs_replaceOptions(_hs_findSelect(form, groupNames[i], j + 1),
- _hs_findOptions(_hs_options[groupNames[i]][j], _hs_defaults[groupNames[i]].slice(0, j + 1)));
- }
- }
- } catch (e) {
- if (!(e instanceof TypeError)) {
- throw e;
- }
- }
- }
-}
-
-function _hs_setupOnReset(form, groupNames)
-{
- setTimeout(function() { _hs_onReset(form, groupNames); }, 25);
-}
-
-function _hs_onReload()
-{
- var ctl;
- for (var i = 0; i < document.forms.length; i++) {
- for (var j in _hs_defaults) {
- if (ctl = _hs_findSelect(document.forms[i], j, 0)) {
- for (var k = 0; k < _hs_defaults[j].length; k++) {
- _hs_setValue(_hs_findSelect(document.forms[i], j, k), _hs_defaults[j][k]);
- }
- }
- }
- }
-
- if (_hs_prevOnload) {
- _hs_prevOnload();
- }
-}
-
-var _hs_prevOnload = null;
-if (window.onload) {
- _hs_prevOnload = window.onload;
-}
-window.onload = _hs_onReload;
-
-var _hs_options = {};
-var _hs_defaults = {};
-
-JAVASCRIPT;
- define('HTML_QUICKFORM_HIERSELECT_EXISTS', true);
- }
- // option lists
- $jsParts = array();
- for ($i = 1; $i < $this->_nbElements; $i++) {
- $jsParts[] = $this->_convertArrayToJavascript($this->_prepareOptions($this->_options[$i], $i));
- }
- $this->_js .= "\n_hs_options['" . $this->_escapeString($this->getName()) . "'] = [\n" .
- implode(",\n", $jsParts) .
- "\n];\n";
- // default value; if we don't actually have any values yet just use
- // the first option (for single selects) or empty array (for multiple)
- $values = array();
- foreach (array_keys($this->_elements) as $key) {
- if (is_array($v = $this->_elements[$key]->getValue())) {
- $values[] = count($v) > 1? $v: $v[0];
- } else {
- // XXX: accessing the supposedly private _options array
- $values[] = $this->_elements[$key]->getMultiple() || empty($this->_elements[$key]->_options[0])?
- array():
- $this->_elements[$key]->_options[0]['attr']['value'];
- }
- }
- $this->_js .= "_hs_defaults['" . $this->_escapeString($this->getName()) . "'] = " .
- $this->_convertArrayToJavascript($values) . ";\n";
- }
- include_once('HTML/QuickForm/Renderer/Default.php');
- $renderer =& new HTML_QuickForm_Renderer_Default();
- $renderer->setElementTemplate('{element}');
- parent::accept($renderer);
-
- if (!empty($onChange)) {
- $keys = array_keys($this->_elements);
- for ($i = 0; $i < count($keys) - 1; $i++) {
- $this->_elements[$keys[$i]]->updateAttributes(array('onchange' => $onChange[$i]));
- }
- }
- return (empty($this->_js)? '': "<script type=\"text/javascript\">\n//<![CDATA[\n" . $this->_js . "//]]>\n</script>") .
- $renderer->toHtml();
- } // end func toHtml
-
- // }}}
- // {{{ accept()
-
- function accept(&$renderer, $required = false, $error = null)
- {
- $renderer->renderElement($this, $required, $error);
- } // end func accept
-
- // }}}
- // {{{ onQuickFormEvent()
-
- function onQuickFormEvent($event, $arg, &$caller)
- {
- if ('updateValue' == $event) {
- // we need to call setValue() so that the secondary option
- // matches the main option
- return HTML_QuickForm_element::onQuickFormEvent($event, $arg, $caller);
- } else {
- $ret = parent::onQuickFormEvent($event, $arg, $caller);
- // add onreset handler to form to properly reset hierselect (see bug #2970)
- if ('addElement' == $event) {
- $onReset = $caller->getAttribute('onreset');
- if (strlen($onReset)) {
- if (strpos($onReset, '_hs_setupOnReset')) {
- $caller->updateAttributes(array('onreset' => str_replace('_hs_setupOnReset(this, [', "_hs_setupOnReset(this, ['" . $this->_escapeString($this->getName()) . "', ", $onReset)));
- } else {
- $caller->updateAttributes(array('onreset' => "var temp = function() { {$onReset} } ; if (!temp()) { return false; } ; if (typeof _hs_setupOnReset != 'undefined') { return _hs_setupOnReset(this, ['" . $this->_escapeString($this->getName()) . "']); } "));
- }
- } else {
- $caller->updateAttributes(array('onreset' => "if (typeof _hs_setupOnReset != 'undefined') { return _hs_setupOnReset(this, ['" . $this->_escapeString($this->getName()) . "']); } "));
- }
- }
- return $ret;
- }
- } // end func onQuickFormEvent
-
- // }}}
- // {{{ _prepareOptions()
-
- /**
- * Prepares options for JS encoding
- *
- * We need to preserve order of options when adding them via javascript, so
- * cannot use object literal and for/in loop (see bug #16603). Therefore we
- * convert an associative array of options to two arrays of their values
- * and texts. Backport from HTML_QuickForm2.
- *
- * @param array Options array
- * @param int Depth within options array
- * @link http://pear.php.net/bugs/bug.php?id=16603
- * @return array
- * @access private
- */
- function _prepareOptions($ary, $depth)
- {
- if (!is_array($ary)) {
- $ret = $ary;
- } elseif (0 == $depth) {
- $ret = array('values' => array_keys($ary), 'texts' => array_values($ary));
- } else {
- $ret = array();
- foreach ($ary as $k => $v) {
- $ret[$k] = $this->_prepareOptions($v, $depth - 1);
- }
- }
- return $ret;
- }
-
- // }}}
- // {{{ _convertArrayToJavascript()
-
- /**
- * Converts PHP array to its Javascript analog
- *
- * @access private
- * @param array PHP array to convert
- * @return string Javascript representation of the value
- */
- function _convertArrayToJavascript($array)
- {
- if (!is_array($array)) {
- return $this->_convertScalarToJavascript($array);
- } elseif (count($array) && array_keys($array) != range(0, count($array) - 1)) {
- return '{' . implode(',', array_map(
- array($this, '_encodeNameValue'),
- array_keys($array), array_values($array)
- )) . '}';
- } else {
- return '[' . implode(',', array_map(
- array($this, '_convertArrayToJavascript'),
- $array
- )) . ']';
- }
- }
-
- // }}}
- // {{{ _encodeNameValue()
-
- /**
- * Callback for array_map used to generate JS name-value pairs
- *
- * @param mixed
- * @param mixed
- * @return string
- */
- function _encodeNameValue($name, $value)
- {
- return $this->_convertScalarToJavascript((string)$name) . ':'
- . $this->_convertArrayToJavascript($value);
- }
-
- // }}}
- // {{{ _convertScalarToJavascript()
-
- /**
- * Converts PHP's scalar value to its Javascript analog
- *
- * @access private
- * @param mixed PHP value to convert
- * @return string Javascript representation of the value
- */
- function _convertScalarToJavascript($val)
- {
- if (is_bool($val)) {
- return $val ? 'true' : 'false';
- } elseif (is_int($val) || is_double($val)) {
- return $val;
- } elseif (is_string($val)) {
- return "'" . $this->_escapeString($val) . "'";
- } elseif (is_null($val)) {
- return 'null';
- } else {
- // don't bother
- return '{}';
- }
- }
-
- // }}}
- // {{{ _escapeString()
-
- /**
- * Quotes the string so that it can be used in Javascript string constants
- *
- * @access private
- * @param string
- * @return string
- */
- function _escapeString($str)
- {
- return strtr($str,array(
- "\r" => '\r',
- "\n" => '\n',
- "\t" => '\t',
- "'" => "\\'",
- '"' => '\"',
- '\\' => '\\\\'
- ));
- }
-
- // }}}
-} // end class HTML_QuickForm_hierselect
-?>
\ No newline at end of file
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * A pseudo-element used for adding raw HTML to form
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Alexey Borzov <avb@php.net>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * HTML class for static data
- */
-require_once 'HTML/QuickForm/static.php';
-
-/**
- * A pseudo-element used for adding raw HTML to form
- *
- * Intended for use with the default renderer only, template-based
- * ones may (and probably will) completely ignore this
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Alexey Borzov <avb@php.net>
- * @version Release: 3.2.16
- * @since 3.0
- * @deprecated Please use the templates rather than add raw HTML via this element
- */
-class HTML_QuickForm_html extends HTML_QuickForm_static
-{
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string $text raw HTML to add
- * @access public
- * @return void
- */
- function HTML_QuickForm_html($text = null)
- {
- $this->HTML_QuickForm_static(null, null, $text);
- $this->_type = 'html';
- }
-
- // }}}
- // {{{ accept()
-
- /**
- * Accepts a renderer
- *
- * @param HTML_QuickForm_Renderer renderer object (only works with Default renderer!)
- * @param bool $sc1 unused, for signature compatibility
- * @param bool $sc2 unused, for signature compatibility
- * @access public
- * @return void
- */
- function accept(&$renderer, $sc1 = false, $sc2 = null)
- {
- $renderer->renderHtml($this);
- } // end func accept
-
- // }}}
-
-} //end class HTML_QuickForm_html
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * HTML class for an <input type="image" /> element
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Base class for <input /> form elements
- */
-require_once 'HTML/QuickForm/input.php';
-
-/**
- * HTML class for an <input type="image" /> element
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @version Release: 3.2.16
- * @since 1.0
- */
-class HTML_QuickForm_image extends HTML_QuickForm_input
-{
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string $elementName (optional)Element name attribute
- * @param string $src (optional)Image source
- * @param mixed $attributes (optional)Either a typical HTML attribute string
- * or an associative array
- * @since 1.0
- * @access public
- * @return void
- */
- function HTML_QuickForm_image($elementName=null, $src='', $attributes=null)
- {
- HTML_QuickForm_input::HTML_QuickForm_input($elementName, null, $attributes);
- $this->setType('image');
- $this->setSource($src);
- } // end class constructor
-
- // }}}
- // {{{ setSource()
-
- /**
- * Sets source for image element
- *
- * @param string $src source for image element
- * @since 1.0
- * @access public
- * @return void
- */
- function setSource($src)
- {
- $this->updateAttributes(array('src' => $src));
- } // end func setSource
-
- // }}}
- // {{{ setBorder()
-
- /**
- * Sets border size for image element
- *
- * @param string $border border for image element
- * @since 1.0
- * @access public
- * @return void
- */
- function setBorder($border)
- {
- $this->updateAttributes(array('border' => $border));
- } // end func setBorder
-
- // }}}
- // {{{ setAlign()
-
- /**
- * Sets alignment for image element
- *
- * @param string $align alignment for image element
- * @since 1.0
- * @access public
- * @return void
- */
- function setAlign($align)
- {
- $this->updateAttributes(array('align' => $align));
- } // end func setAlign
-
- // }}}
- // {{{ freeze()
-
- /**
- * Freeze the element so that only its value is returned
- *
- * @access public
- * @return void
- */
- function freeze()
- {
- return false;
- } //end func freeze
-
- // }}}
-
-} // end class HTML_QuickForm_image
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Base class for <input /> form elements
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Base class for form elements
- */
-require_once 'HTML/QuickForm/element.php';
-
-/**
- * Base class for <input /> form elements
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @version Release: 3.2.16
- * @since 1.0
- * @abstract
- */
-class HTML_QuickForm_input extends HTML_QuickForm_element
-{
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string Input field name attribute
- * @param mixed Label(s) for the input field
- * @param mixed Either a typical HTML attribute string or an associative array
- * @since 1.0
- * @access public
- * @return void
- */
- function HTML_QuickForm_input($elementName=null, $elementLabel=null, $attributes=null)
- {
- $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes);
- } //end constructor
-
- // }}}
- // {{{ setType()
-
- /**
- * Sets the element type
- *
- * @param string $type Element type
- * @since 1.0
- * @access public
- * @return void
- */
- function setType($type)
- {
- $this->_type = $type;
- $this->updateAttributes(array('type'=>$type));
- } // end func setType
-
- // }}}
- // {{{ setName()
-
- /**
- * Sets the input field name
- *
- * @param string $name Input field name attribute
- * @since 1.0
- * @access public
- * @return void
- */
- function setName($name)
- {
- $this->updateAttributes(array('name'=>$name));
- } //end func setName
-
- // }}}
- // {{{ getName()
-
- /**
- * Returns the element name
- *
- * @since 1.0
- * @access public
- * @return string
- */
- function getName()
- {
- return $this->getAttribute('name');
- } //end func getName
-
- // }}}
- // {{{ setValue()
-
- /**
- * Sets the value of the form element
- *
- * @param string $value Default value of the form element
- * @since 1.0
- * @access public
- * @return void
- */
- function setValue($value)
- {
- $this->updateAttributes(array('value'=>$value));
- } // end func setValue
-
- // }}}
- // {{{ getValue()
-
- /**
- * Returns the value of the form element
- *
- * @since 1.0
- * @access public
- * @return string
- */
- function getValue()
- {
- return $this->getAttribute('value');
- } // end func getValue
-
- // }}}
- // {{{ toHtml()
-
- /**
- * Returns the input field in HTML
- *
- * @since 1.0
- * @access public
- * @return string
- */
- function toHtml()
- {
- if ($this->_flagFrozen) {
- return $this->getFrozenHtml();
- } else {
- return $this->_getTabs() . '<input' . $this->_getAttrString($this->_attributes) . ' />';
- }
- } //end func toHtml
-
- // }}}
- // {{{ onQuickFormEvent()
-
- /**
- * Called by HTML_QuickForm whenever form event is made on this element
- *
- * @param string $event Name of event
- * @param mixed $arg event arguments
- * @param object &$caller calling object
- * @since 1.0
- * @access public
- * @return void
- * @throws
- */
- function onQuickFormEvent($event, $arg, &$caller)
- {
- // do not use submit values for button-type elements
- $type = $this->getType();
- if (('updateValue' != $event) ||
- ('submit' != $type && 'reset' != $type && 'image' != $type && 'button' != $type)) {
- parent::onQuickFormEvent($event, $arg, $caller);
- } else {
- $value = $this->_findValue($caller->_constantValues);
- if (null === $value) {
- $value = $this->_findValue($caller->_defaultValues);
- }
- if (null !== $value) {
- $this->setValue($value);
- }
- }
- return true;
- } // end func onQuickFormEvent
-
- // }}}
- // {{{ exportValue()
-
- /**
- * We don't need values from button-type elements (except submit) and files
- */
- function exportValue(&$submitValues, $assoc = false)
- {
- $type = $this->getType();
- if ('reset' == $type || 'image' == $type || 'button' == $type || 'file' == $type) {
- return null;
- } else {
- return parent::exportValue($submitValues, $assoc);
- }
- }
-
- // }}}
-} // end class HTML_QuickForm_element
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * HTML class for a link type field
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * HTML class for static data
- */
-require_once 'HTML/QuickForm/static.php';
-
-/**
- * HTML class for a link type field
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @version Release: 3.2.16
- * @since 2.0
- */
-class HTML_QuickForm_link extends HTML_QuickForm_static
-{
- // {{{ properties
-
- /**
- * Link display text
- * @var string
- * @since 1.0
- * @access private
- */
- var $_text = "";
-
- // }}}
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string $elementLabel (optional)Link label
- * @param string $href (optional)Link href
- * @param string $text (optional)Link display text
- * @param mixed $attributes (optional)Either a typical HTML attribute string
- * or an associative array
- * @since 1.0
- * @access public
- * @return void
- * @throws
- */
- function HTML_QuickForm_link($elementName=null, $elementLabel=null, $href=null, $text=null, $attributes=null)
- {
- HTML_QuickForm_element::HTML_QuickForm_element($elementName, $elementLabel, $attributes);
- $this->_persistantFreeze = false;
- $this->_type = 'link';
- $this->setHref($href);
- $this->_text = $text;
- } //end constructor
-
- // }}}
- // {{{ setName()
-
- /**
- * Sets the input field name
- *
- * @param string $name Input field name attribute
- * @since 1.0
- * @access public
- * @return void
- * @throws
- */
- function setName($name)
- {
- $this->updateAttributes(array('name'=>$name));
- } //end func setName
-
- // }}}
- // {{{ getName()
-
- /**
- * Returns the element name
- *
- * @since 1.0
- * @access public
- * @return string
- * @throws
- */
- function getName()
- {
- return $this->getAttribute('name');
- } //end func getName
-
- // }}}
- // {{{ setValue()
-
- /**
- * Sets value for textarea element
- *
- * @param string $value Value for password element
- * @since 1.0
- * @access public
- * @return void
- * @throws
- */
- function setValue($value)
- {
- return;
- } //end func setValue
-
- // }}}
- // {{{ getValue()
-
- /**
- * Returns the value of the form element
- *
- * @since 1.0
- * @access public
- * @return void
- * @throws
- */
- function getValue()
- {
- return;
- } // end func getValue
-
-
- // }}}
- // {{{ setHref()
-
- /**
- * Sets the links href
- *
- * @param string $href
- * @since 1.0
- * @access public
- * @return void
- * @throws
- */
- function setHref($href)
- {
- $this->updateAttributes(array('href'=>$href));
- } // end func setHref
-
- // }}}
- // {{{ toHtml()
-
- /**
- * Returns the textarea element in HTML
- *
- * @since 1.0
- * @access public
- * @return string
- * @throws
- */
- function toHtml()
- {
- $tabs = $this->_getTabs();
- $html = "$tabs<a".$this->_getAttrString($this->_attributes).">";
- $html .= $this->_text;
- $html .= "</a>";
- return $html;
- } //end func toHtml
-
- // }}}
- // {{{ getFrozenHtml()
-
- /**
- * Returns the value of field without HTML tags (in this case, value is changed to a mask)
- *
- * @since 1.0
- * @access public
- * @return string
- * @throws
- */
- function getFrozenHtml()
- {
- return;
- } //end func getFrozenHtml
-
- // }}}
-
-} //end class HTML_QuickForm_textarea
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * HTML class for a password type field
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Base class for <input /> form elements
- */
-require_once 'HTML/QuickForm/input.php';
-
-/**
- * HTML class for a password type field
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @version Release: 3.2.16
- * @since 1.0
- */
-class HTML_QuickForm_password extends HTML_QuickForm_input
-{
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string $elementName (optional)Input field name attribute
- * @param string $elementLabel (optional)Input field label
- * @param mixed $attributes (optional)Either a typical HTML attribute string
- * or an associative array
- * @since 1.0
- * @access public
- * @return void
- * @throws
- */
- function HTML_QuickForm_password($elementName=null, $elementLabel=null, $attributes=null)
- {
- HTML_QuickForm_input::HTML_QuickForm_input($elementName, $elementLabel, $attributes);
- $this->setType('password');
- } //end constructor
-
- // }}}
- // {{{ setSize()
-
- /**
- * Sets size of password element
- *
- * @param string $size Size of password field
- * @since 1.0
- * @access public
- * @return void
- */
- function setSize($size)
- {
- $this->updateAttributes(array('size'=>$size));
- } //end func setSize
-
- // }}}
- // {{{ setMaxlength()
-
- /**
- * Sets maxlength of password element
- *
- * @param string $maxlength Maximum length of password field
- * @since 1.0
- * @access public
- * @return void
- */
- function setMaxlength($maxlength)
- {
- $this->updateAttributes(array('maxlength'=>$maxlength));
- } //end func setMaxlength
-
- // }}}
- // {{{ getFrozenHtml()
-
- /**
- * Returns the value of field without HTML tags (in this case, value is changed to a mask)
- *
- * @since 1.0
- * @access public
- * @return string
- * @throws
- */
- function getFrozenHtml()
- {
- $value = $this->getValue();
- return ('' != $value? '**********': ' ') .
- $this->_getPersistantData();
- } //end func getFrozenHtml
-
- // }}}
-
-} //end class HTML_QuickForm_password
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * HTML class for a radio type element
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Base class for <input /> form elements
- */
-require_once 'HTML/QuickForm/input.php';
-
-/**
- * HTML class for a radio type element
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @version Release: 3.2.16
- * @since 1.0
- */
-class HTML_QuickForm_radio extends HTML_QuickForm_input
-{
- // {{{ properties
-
- /**
- * Radio display text
- * @var string
- * @since 1.1
- * @access private
- */
- var $_text = '';
-
- // }}}
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string Input field name attribute
- * @param mixed Label(s) for a field
- * @param string Text to display near the radio
- * @param string Input field value
- * @param mixed Either a typical HTML attribute string or an associative array
- * @since 1.0
- * @access public
- * @return void
- */
- function HTML_QuickForm_radio($elementName=null, $elementLabel=null, $text=null, $value=null, $attributes=null)
- {
- $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes);
- if (isset($value)) {
- $this->setValue($value);
- }
- $this->_persistantFreeze = true;
- $this->setType('radio');
- $this->_text = $text;
- $this->_generateId();
- } //end constructor
-
- // }}}
- // {{{ setChecked()
-
- /**
- * Sets whether radio button is checked
- *
- * @param bool $checked Whether the field is checked or not
- * @since 1.0
- * @access public
- * @return void
- */
- function setChecked($checked)
- {
- if (!$checked) {
- $this->removeAttribute('checked');
- } else {
- $this->updateAttributes(array('checked'=>'checked'));
- }
- } //end func setChecked
-
- // }}}
- // {{{ getChecked()
-
- /**
- * Returns whether radio button is checked
- *
- * @since 1.0
- * @access public
- * @return string
- */
- function getChecked()
- {
- return $this->getAttribute('checked');
- } //end func getChecked
-
- // }}}
- // {{{ toHtml()
-
- /**
- * Returns the radio element in HTML
- *
- * @since 1.0
- * @access public
- * @return string
- */
- function toHtml()
- {
- if (0 == strlen($this->_text)) {
- $label = '';
- } elseif ($this->_flagFrozen) {
- $label = $this->_text;
- } else {
- $label = '<label for="' . $this->getAttribute('id') . '">' . $this->_text . '</label>';
- }
- return HTML_QuickForm_input::toHtml() . $label;
- } //end func toHtml
-
- // }}}
- // {{{ getFrozenHtml()
-
- /**
- * Returns the value of field without HTML tags
- *
- * @since 1.0
- * @access public
- * @return string
- */
- function getFrozenHtml()
- {
- if ($this->getChecked()) {
- return '<tt>(x)</tt>' .
- $this->_getPersistantData();
- } else {
- return '<tt>( )</tt>';
- }
- } //end func getFrozenHtml
-
- // }}}
- // {{{ setText()
-
- /**
- * Sets the radio text
- *
- * @param string $text Text to display near the radio button
- * @since 1.1
- * @access public
- * @return void
- */
- function setText($text)
- {
- $this->_text = $text;
- } //end func setText
-
- // }}}
- // {{{ getText()
-
- /**
- * Returns the radio text
- *
- * @since 1.1
- * @access public
- * @return string
- */
- function getText()
- {
- return $this->_text;
- } //end func getText
-
- // }}}
- // {{{ onQuickFormEvent()
-
- /**
- * Called by HTML_QuickForm whenever form event is made on this element
- *
- * @param string $event Name of event
- * @param mixed $arg event arguments
- * @param object &$caller calling object
- * @since 1.0
- * @access public
- * @return void
- */
- function onQuickFormEvent($event, $arg, &$caller)
- {
- switch ($event) {
- case 'updateValue':
- // constant values override both default and submitted ones
- // default values are overriden by submitted
- $value = $this->_findValue($caller->_constantValues);
- if (null === $value) {
- $value = $this->_findValue($caller->_submitValues);
- if (null === $value) {
- $value = $this->_findValue($caller->_defaultValues);
- }
- }
- if (!is_null($value) && $value == $this->getValue()) {
- $this->setChecked(true);
- } else {
- $this->setChecked(false);
- }
- break;
- case 'setGroupValue':
- if ($arg == $this->getValue()) {
- $this->setChecked(true);
- } else {
- $this->setChecked(false);
- }
- break;
- default:
- parent::onQuickFormEvent($event, $arg, $caller);
- }
- return true;
- } // end func onQuickFormLoad
-
- // }}}
- // {{{ exportValue()
-
- /**
- * Returns the value attribute if the radio is checked, null if it is not
- */
- function exportValue(&$submitValues, $assoc = false)
- {
- $value = $this->_findValue($submitValues);
- if (null === $value) {
- $value = $this->getChecked()? $this->getValue(): null;
- } elseif ($value != $this->getValue()) {
- $value = null;
- }
- return $this->_prepareValue($value, $assoc);
- }
-
- // }}}
-} //end class HTML_QuickForm_radio
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * HTML class for a reset type element
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Base class for <input /> form elements
- */
-require_once 'HTML/QuickForm/input.php';
-
-/**
- * HTML class for a reset type element
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @version Release: 3.2.16
- * @since 1.0
- */
-class HTML_QuickForm_reset extends HTML_QuickForm_input
-{
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string $elementName (optional)Input field name attribute
- * @param string $value (optional)Input field value
- * @param mixed $attributes (optional)Either a typical HTML attribute string
- * or an associative array
- * @since 1.0
- * @access public
- * @return void
- */
- function HTML_QuickForm_reset($elementName=null, $value=null, $attributes=null)
- {
- HTML_QuickForm_input::HTML_QuickForm_input($elementName, null, $attributes);
- $this->setValue($value);
- $this->setType('reset');
- } //end constructor
-
- // }}}
- // {{{ freeze()
-
- /**
- * Freeze the element so that only its value is returned
- *
- * @access public
- * @return void
- */
- function freeze()
- {
- return false;
- } //end func freeze
-
- // }}}
-
-} //end class HTML_QuickForm_reset
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Class to dynamically create an HTML SELECT
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Alexey Borzov <avb@php.net>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Base class for form elements
- */
-require_once 'HTML/QuickForm/element.php';
-
-/**
- * Class to dynamically create an HTML SELECT
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Alexey Borzov <avb@php.net>
- * @version Release: 3.2.16
- * @since 1.0
- */
-class HTML_QuickForm_select extends HTML_QuickForm_element {
-
- // {{{ properties
-
- /**
- * Contains the select options
- *
- * @var array
- * @since 1.0
- * @access private
- */
- var $_options = array();
-
- /**
- * Default values of the SELECT
- *
- * @var string
- * @since 1.0
- * @access private
- */
- var $_values = null;
-
- // }}}
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string Select name attribute
- * @param mixed Label(s) for the select
- * @param mixed Data to be used to populate options
- * @param mixed Either a typical HTML attribute string or an associative array
- * @since 1.0
- * @access public
- * @return void
- */
- function HTML_QuickForm_select($elementName=null, $elementLabel=null, $options=null, $attributes=null)
- {
- HTML_QuickForm_element::HTML_QuickForm_element($elementName, $elementLabel, $attributes);
- $this->_persistantFreeze = true;
- $this->_type = 'select';
- if (isset($options)) {
- $this->load($options);
- }
- } //end constructor
-
- // }}}
- // {{{ apiVersion()
-
- /**
- * Returns the current API version
- *
- * @since 1.0
- * @access public
- * @return double
- */
- function apiVersion()
- {
- return 2.3;
- } //end func apiVersion
-
- // }}}
- // {{{ setSelected()
-
- /**
- * Sets the default values of the select box
- *
- * @param mixed $values Array or comma delimited string of selected values
- * @since 1.0
- * @access public
- * @return void
- */
- function setSelected($values)
- {
- if (is_string($values) && $this->getMultiple()) {
- $values = preg_split("/[ ]?,[ ]?/", $values);
- }
- if (is_array($values)) {
- $this->_values = array_values($values);
- } else {
- $this->_values = array($values);
- }
- } //end func setSelected
-
- // }}}
- // {{{ getSelected()
-
- /**
- * Returns an array of the selected values
- *
- * @since 1.0
- * @access public
- * @return array of selected values
- */
- function getSelected()
- {
- return $this->_values;
- } // end func getSelected
-
- // }}}
- // {{{ setName()
-
- /**
- * Sets the input field name
- *
- * @param string $name Input field name attribute
- * @since 1.0
- * @access public
- * @return void
- */
- function setName($name)
- {
- $this->updateAttributes(array('name' => $name));
- } //end func setName
-
- // }}}
- // {{{ getName()
-
- /**
- * Returns the element name
- *
- * @since 1.0
- * @access public
- * @return string
- */
- function getName()
- {
- return $this->getAttribute('name');
- } //end func getName
-
- // }}}
- // {{{ getPrivateName()
-
- /**
- * Returns the element name (possibly with brackets appended)
- *
- * @since 1.0
- * @access public
- * @return string
- */
- function getPrivateName()
- {
- if ($this->getAttribute('multiple')) {
- return $this->getName() . '[]';
- } else {
- return $this->getName();
- }
- } //end func getPrivateName
-
- // }}}
- // {{{ setValue()
-
- /**
- * Sets the value of the form element
- *
- * @param mixed $values Array or comma delimited string of selected values
- * @since 1.0
- * @access public
- * @return void
- */
- function setValue($value)
- {
- $this->setSelected($value);
- } // end func setValue
-
- // }}}
- // {{{ getValue()
-
- /**
- * Returns an array of the selected values
- *
- * @since 1.0
- * @access public
- * @return array of selected values
- */
- function getValue()
- {
- return $this->_values;
- } // end func getValue
-
- // }}}
- // {{{ setSize()
-
- /**
- * Sets the select field size, only applies to 'multiple' selects
- *
- * @param int $size Size of select field
- * @since 1.0
- * @access public
- * @return void
- */
- function setSize($size)
- {
- $this->updateAttributes(array('size' => $size));
- } //end func setSize
-
- // }}}
- // {{{ getSize()
-
- /**
- * Returns the select field size
- *
- * @since 1.0
- * @access public
- * @return int
- */
- function getSize()
- {
- return $this->getAttribute('size');
- } //end func getSize
-
- // }}}
- // {{{ setMultiple()
-
- /**
- * Sets the select mutiple attribute
- *
- * @param bool $multiple Whether the select supports multi-selections
- * @since 1.2
- * @access public
- * @return void
- */
- function setMultiple($multiple)
- {
- if ($multiple) {
- $this->updateAttributes(array('multiple' => 'multiple'));
- } else {
- $this->removeAttribute('multiple');
- }
- } //end func setMultiple
-
- // }}}
- // {{{ getMultiple()
-
- /**
- * Returns the select mutiple attribute
- *
- * @since 1.2
- * @access public
- * @return bool true if multiple select, false otherwise
- */
- function getMultiple()
- {
- return (bool)$this->getAttribute('multiple');
- } //end func getMultiple
-
- // }}}
- // {{{ addOption()
-
- /**
- * Adds a new OPTION to the SELECT
- *
- * @param string $text Display text for the OPTION
- * @param string $value Value for the OPTION
- * @param mixed $attributes Either a typical HTML attribute string
- * or an associative array
- * @since 1.0
- * @access public
- * @return void
- */
- function addOption($text, $value, $attributes=null)
- {
- if (null === $attributes) {
- $attributes = array('value' => (string)$value);
- } else {
- $attributes = $this->_parseAttributes($attributes);
- if (isset($attributes['selected'])) {
- // the 'selected' attribute will be set in toHtml()
- $this->_removeAttr('selected', $attributes);
- if (is_null($this->_values)) {
- $this->_values = array($value);
- } elseif (!in_array($value, $this->_values)) {
- $this->_values[] = $value;
- }
- }
- $this->_updateAttrArray($attributes, array('value' => (string)$value));
- }
- $this->_options[] = array('text' => $text, 'attr' => $attributes);
- } // end func addOption
-
- // }}}
- // {{{ loadArray()
-
- /**
- * Loads the options from an associative array
- *
- * @param array $arr Associative array of options
- * @param mixed $values (optional) Array or comma delimited string of selected values
- * @since 1.0
- * @access public
- * @return PEAR_Error on error or true
- * @throws PEAR_Error
- */
- function loadArray($arr, $values=null)
- {
- if (!is_array($arr)) {
- return PEAR::raiseError('Argument 1 of HTML_Select::loadArray is not a valid array');
- }
- if (isset($values)) {
- $this->setSelected($values);
- }
- foreach ($arr as $key => $val) {
- // Warning: new API since release 2.3
- $this->addOption($val, $key);
- }
- return true;
- } // end func loadArray
-
- // }}}
- // {{{ loadDbResult()
-
- /**
- * Loads the options from DB_result object
- *
- * If no column names are specified the first two columns of the result are
- * used as the text and value columns respectively
- * @param object $result DB_result object
- * @param string $textCol (optional) Name of column to display as the OPTION text
- * @param string $valueCol (optional) Name of column to use as the OPTION value
- * @param mixed $values (optional) Array or comma delimited string of selected values
- * @since 1.0
- * @access public
- * @return PEAR_Error on error or true
- * @throws PEAR_Error
- */
- function loadDbResult(&$result, $textCol=null, $valueCol=null, $values=null)
- {
- if (!is_object($result) || !is_a($result, 'db_result')) {
- return PEAR::raiseError('Argument 1 of HTML_Select::loadDbResult is not a valid DB_result');
- }
- if (isset($values)) {
- $this->setValue($values);
- }
- $fetchMode = ($textCol && $valueCol) ? DB_FETCHMODE_ASSOC : DB_FETCHMODE_ORDERED;
- while (is_array($row = $result->fetchRow($fetchMode)) ) {
- if ($fetchMode == DB_FETCHMODE_ASSOC) {
- $this->addOption($row[$textCol], $row[$valueCol]);
- } else {
- $this->addOption($row[0], $row[1]);
- }
- }
- return true;
- } // end func loadDbResult
-
- // }}}
- // {{{ loadQuery()
-
- /**
- * Queries a database and loads the options from the results
- *
- * @param mixed $conn Either an existing DB connection or a valid dsn
- * @param string $sql SQL query string
- * @param string $textCol (optional) Name of column to display as the OPTION text
- * @param string $valueCol (optional) Name of column to use as the OPTION value
- * @param mixed $values (optional) Array or comma delimited string of selected values
- * @since 1.1
- * @access public
- * @return void
- * @throws PEAR_Error
- */
- function loadQuery(&$conn, $sql, $textCol=null, $valueCol=null, $values=null)
- {
- if (is_string($conn)) {
- require_once('DB.php');
- $dbConn = &DB::connect($conn, true);
- if (DB::isError($dbConn)) {
- return $dbConn;
- }
- } elseif (is_subclass_of($conn, "db_common")) {
- $dbConn = &$conn;
- } else {
- return PEAR::raiseError('Argument 1 of HTML_Select::loadQuery is not a valid type');
- }
- $result = $dbConn->query($sql);
- if (DB::isError($result)) {
- return $result;
- }
- $this->loadDbResult($result, $textCol, $valueCol, $values);
- $result->free();
- if (is_string($conn)) {
- $dbConn->disconnect();
- }
- return true;
- } // end func loadQuery
-
- // }}}
- // {{{ load()
-
- /**
- * Loads options from different types of data sources
- *
- * This method is a simulated overloaded method. The arguments, other than the
- * first are optional and only mean something depending on the type of the first argument.
- * If the first argument is an array then all arguments are passed in order to loadArray.
- * If the first argument is a db_result then all arguments are passed in order to loadDbResult.
- * If the first argument is a string or a DB connection then all arguments are
- * passed in order to loadQuery.
- * @param mixed $options Options source currently supports assoc array or DB_result
- * @param mixed $param1 (optional) See function detail
- * @param mixed $param2 (optional) See function detail
- * @param mixed $param3 (optional) See function detail
- * @param mixed $param4 (optional) See function detail
- * @since 1.1
- * @access public
- * @return PEAR_Error on error or true
- * @throws PEAR_Error
- */
- function load(&$options, $param1=null, $param2=null, $param3=null, $param4=null)
- {
- switch (true) {
- case is_array($options):
- return $this->loadArray($options, $param1);
- break;
- case (is_a($options, 'db_result')):
- return $this->loadDbResult($options, $param1, $param2, $param3);
- break;
- case (is_string($options) && !empty($options) || is_subclass_of($options, "db_common")):
- return $this->loadQuery($options, $param1, $param2, $param3, $param4);
- break;
- }
- } // end func load
-
- // }}}
- // {{{ toHtml()
-
- /**
- * Returns the SELECT in HTML
- *
- * @since 1.0
- * @access public
- * @return string
- */
- function toHtml()
- {
- if ($this->_flagFrozen) {
- return $this->getFrozenHtml();
- } else {
- $tabs = $this->_getTabs();
- $strHtml = '';
-
- if ($this->getComment() != '') {
- $strHtml .= $tabs . '<!-- ' . $this->getComment() . " //-->\n";
- }
-
- if (!$this->getMultiple()) {
- $attrString = $this->_getAttrString($this->_attributes);
- } else {
- $myName = $this->getName();
- $this->setName($myName . '[]');
- $attrString = $this->_getAttrString($this->_attributes);
- $this->setName($myName);
- }
- $strHtml .= $tabs . '<select' . $attrString . ">\n";
-
- $strValues = is_array($this->_values)? array_map('strval', $this->_values): array();
- foreach ($this->_options as $option) {
- if (!empty($strValues) && in_array($option['attr']['value'], $strValues, true)) {
- $option['attr']['selected'] = 'selected';
- }
- $strHtml .= $tabs . "\t<option" . $this->_getAttrString($option['attr']) . '>' .
- $option['text'] . "</option>\n";
- }
-
- return $strHtml . $tabs . '</select>';
- }
- } //end func toHtml
-
- // }}}
- // {{{ getFrozenHtml()
-
- /**
- * Returns the value of field without HTML tags
- *
- * @since 1.0
- * @access public
- * @return string
- */
- function getFrozenHtml()
- {
- $value = array();
- if (is_array($this->_values)) {
- foreach ($this->_values as $key => $val) {
- for ($i = 0, $optCount = count($this->_options); $i < $optCount; $i++) {
- if (0 == strcmp($val, $this->_options[$i]['attr']['value'])) {
- $value[$key] = $this->_options[$i]['text'];
- break;
- }
- }
- }
- }
- $html = empty($value)? ' ': join('<br />', $value);
- if ($this->_persistantFreeze) {
- $name = $this->getPrivateName();
- // Only use id attribute if doing single hidden input
- if (1 == count($value)) {
- $id = $this->getAttribute('id');
- $idAttr = isset($id)? array('id' => $id): array();
- } else {
- $idAttr = array();
- }
- foreach ($value as $key => $item) {
- $html .= '<input' . $this->_getAttrString(array(
- 'type' => 'hidden',
- 'name' => $name,
- 'value' => $this->_values[$key]
- ) + $idAttr) . ' />';
- }
- }
- return $html;
- } //end func getFrozenHtml
-
- // }}}
- // {{{ exportValue()
-
- /**
- * We check the options and return only the values that _could_ have been
- * selected. We also return a scalar value if select is not "multiple"
- */
- function exportValue(&$submitValues, $assoc = false)
- {
- $value = $this->_findValue($submitValues);
- if (is_null($value)) {
- $value = $this->getValue();
- } elseif(!is_array($value)) {
- $value = array($value);
- }
- if (is_array($value) && !empty($this->_options)) {
- $cleanValue = null;
- foreach ($value as $v) {
- for ($i = 0, $optCount = count($this->_options); $i < $optCount; $i++) {
- if (0 == strcmp($v, $this->_options[$i]['attr']['value'])) {
- $cleanValue[] = $v;
- break;
- }
- }
- }
- } else {
- $cleanValue = $value;
- }
- if (is_array($cleanValue) && !$this->getMultiple()) {
- return $this->_prepareValue($cleanValue[0], $assoc);
- } else {
- return $this->_prepareValue($cleanValue, $assoc);
- }
- }
-
- // }}}
- // {{{ onQuickFormEvent()
-
- function onQuickFormEvent($event, $arg, &$caller)
- {
- if ('updateValue' == $event) {
- $value = $this->_findValue($caller->_constantValues);
- if (null === $value) {
- $value = $this->_findValue($caller->_submitValues);
- // Fix for bug #4465 & #5269
- // XXX: should we push this to element::onQuickFormEvent()?
- if (null === $value && (!$caller->isSubmitted() || !$this->getMultiple())) {
- $value = $this->_findValue($caller->_defaultValues);
- }
- }
- if (null !== $value) {
- $this->setValue($value);
- }
- return true;
- } else {
- return parent::onQuickFormEvent($event, $arg, $caller);
- }
- }
-
- // }}}
-} //end class HTML_QuickForm_select
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * HTML class for static data
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Wojciech Gdela <eltehaem@poczta.onet.pl>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Base class for form elements
- */
-require_once 'HTML/QuickForm/element.php';
-
-/**
- * HTML class for static data
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Wojciech Gdela <eltehaem@poczta.onet.pl>
- * @version Release: 3.2.16
- * @since 2.7
- */
-class HTML_QuickForm_static extends HTML_QuickForm_element {
-
- // {{{ properties
-
- /**
- * Display text
- * @var string
- * @access private
- */
- var $_text = null;
-
- // }}}
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string $elementLabel (optional)Label
- * @param string $text (optional)Display text
- * @access public
- * @return void
- */
- function HTML_QuickForm_static($elementName=null, $elementLabel=null, $text=null)
- {
- HTML_QuickForm_element::HTML_QuickForm_element($elementName, $elementLabel);
- $this->_persistantFreeze = false;
- $this->_type = 'static';
- $this->_text = $text;
- } //end constructor
-
- // }}}
- // {{{ setName()
-
- /**
- * Sets the element name
- *
- * @param string $name Element name
- * @access public
- * @return void
- */
- function setName($name)
- {
- $this->updateAttributes(array('name'=>$name));
- } //end func setName
-
- // }}}
- // {{{ getName()
-
- /**
- * Returns the element name
- *
- * @access public
- * @return string
- */
- function getName()
- {
- return $this->getAttribute('name');
- } //end func getName
-
- // }}}
- // {{{ setText()
-
- /**
- * Sets the text
- *
- * @param string $text
- * @access public
- * @return void
- */
- function setText($text)
- {
- $this->_text = $text;
- } // end func setText
-
- // }}}
- // {{{ setValue()
-
- /**
- * Sets the text (uses the standard setValue call to emulate a form element.
- *
- * @param string $text
- * @access public
- * @return void
- */
- function setValue($text)
- {
- $this->setText($text);
- } // end func setValue
-
- // }}}
- // {{{ toHtml()
-
- /**
- * Returns the static text element in HTML
- *
- * @access public
- * @return string
- */
- function toHtml()
- {
- return $this->_getTabs() . $this->_text;
- } //end func toHtml
-
- // }}}
- // {{{ getFrozenHtml()
-
- /**
- * Returns the value of field without HTML tags
- *
- * @access public
- * @return string
- */
- function getFrozenHtml()
- {
- return $this->toHtml();
- } //end func getFrozenHtml
-
- // }}}
- // {{{ onQuickFormEvent()
-
- /**
- * Called by HTML_QuickForm whenever form event is made on this element
- *
- * @param string $event Name of event
- * @param mixed $arg event arguments
- * @param object &$caller calling object
- * @since 1.0
- * @access public
- * @return void
- * @throws
- */
- function onQuickFormEvent($event, $arg, &$caller)
- {
- switch ($event) {
- case 'updateValue':
- // do NOT use submitted values for static elements
- $value = $this->_findValue($caller->_constantValues);
- if (null === $value) {
- $value = $this->_findValue($caller->_defaultValues);
- }
- if (null !== $value) {
- $this->setValue($value);
- }
- break;
- default:
- parent::onQuickFormEvent($event, $arg, $caller);
- }
- return true;
- } // end func onQuickFormEvent
-
- // }}}
- // {{{ exportValue()
-
- /**
- * We override this here because we don't want any values from static elements
- */
- function exportValue(&$submitValues, $assoc = false)
- {
- return null;
- }
-
- // }}}
-} //end class HTML_QuickForm_static
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * HTML class for a submit type element
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Base class for <input /> form elements
- */
-require_once 'HTML/QuickForm/input.php';
-
-/**
- * HTML class for a submit type element
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @version Release: 3.2.16
- * @since 1.0
- */
-class HTML_QuickForm_submit extends HTML_QuickForm_input
-{
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string Input field name attribute
- * @param string Input field value
- * @param mixed Either a typical HTML attribute string or an associative array
- * @since 1.0
- * @access public
- * @return void
- */
- function HTML_QuickForm_submit($elementName=null, $value=null, $attributes=null)
- {
- HTML_QuickForm_input::HTML_QuickForm_input($elementName, null, $attributes);
- $this->setValue($value);
- $this->setType('submit');
- } //end constructor
-
- // }}}
- // {{{ freeze()
-
- /**
- * Freeze the element so that only its value is returned
- *
- * @access public
- * @return void
- */
- function freeze()
- {
- return false;
- } //end func freeze
-
- // }}}
- // {{{ exportValue()
-
- /**
- * Only return the value if it is found within $submitValues (i.e. if
- * this particular submit button was clicked)
- */
- function exportValue(&$submitValues, $assoc = false)
- {
- return $this->_prepareValue($this->_findValue($submitValues), $assoc);
- }
-
- // }}}
-} //end class HTML_QuickForm_submit
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * HTML class for a text field
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Base class for <input /> form elements
- */
-require_once 'HTML/QuickForm/input.php';
-
-/**
- * HTML class for a text field
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @version Release: 3.2.16
- * @since 1.0
- */
-class HTML_QuickForm_text extends HTML_QuickForm_input
-{
-
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string $elementName (optional)Input field name attribute
- * @param string $elementLabel (optional)Input field label
- * @param mixed $attributes (optional)Either a typical HTML attribute string
- * or an associative array
- * @since 1.0
- * @access public
- * @return void
- */
- function HTML_QuickForm_text($elementName=null, $elementLabel=null, $attributes=null)
- {
- HTML_QuickForm_input::HTML_QuickForm_input($elementName, $elementLabel, $attributes);
- $this->_persistantFreeze = true;
- $this->setType('text');
- } //end constructor
-
- // }}}
- // {{{ setSize()
-
- /**
- * Sets size of text field
- *
- * @param string $size Size of text field
- * @since 1.3
- * @access public
- * @return void
- */
- function setSize($size)
- {
- $this->updateAttributes(array('size'=>$size));
- } //end func setSize
-
- // }}}
- // {{{ setMaxlength()
-
- /**
- * Sets maxlength of text field
- *
- * @param string $maxlength Maximum length of text field
- * @since 1.3
- * @access public
- * @return void
- */
- function setMaxlength($maxlength)
- {
- $this->updateAttributes(array('maxlength'=>$maxlength));
- } //end func setMaxlength
-
- // }}}
-
-} //end class HTML_QuickForm_text
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * HTML class for a textarea type field
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Base class for form elements
- */
-require_once 'HTML/QuickForm/element.php';
-
-/**
- * HTML class for a textarea type field
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @version Release: 3.2.16
- * @since 1.0
- */
-class HTML_QuickForm_textarea extends HTML_QuickForm_element
-{
- // {{{ properties
-
- /**
- * Field value
- * @var string
- * @since 1.0
- * @access private
- */
- var $_value = null;
-
- // }}}
- // {{{ constructor
-
- /**
- * Class constructor
- *
- * @param string Input field name attribute
- * @param mixed Label(s) for a field
- * @param mixed Either a typical HTML attribute string or an associative array
- * @since 1.0
- * @access public
- * @return void
- */
- function HTML_QuickForm_textarea($elementName=null, $elementLabel=null, $attributes=null)
- {
- HTML_QuickForm_element::HTML_QuickForm_element($elementName, $elementLabel, $attributes);
- $this->_persistantFreeze = true;
- $this->_type = 'textarea';
- } //end constructor
-
- // }}}
- // {{{ setName()
-
- /**
- * Sets the input field name
- *
- * @param string $name Input field name attribute
- * @since 1.0
- * @access public
- * @return void
- */
- function setName($name)
- {
- $this->updateAttributes(array('name'=>$name));
- } //end func setName
-
- // }}}
- // {{{ getName()
-
- /**
- * Returns the element name
- *
- * @since 1.0
- * @access public
- * @return string
- */
- function getName()
- {
- return $this->getAttribute('name');
- } //end func getName
-
- // }}}
- // {{{ setValue()
-
- /**
- * Sets value for textarea element
- *
- * @param string $value Value for textarea element
- * @since 1.0
- * @access public
- * @return void
- */
- function setValue($value)
- {
- $this->_value = $value;
- } //end func setValue
-
- // }}}
- // {{{ getValue()
-
- /**
- * Returns the value of the form element
- *
- * @since 1.0
- * @access public
- * @return string
- */
- function getValue()
- {
- return $this->_value;
- } // end func getValue
-
- // }}}
- // {{{ setWrap()
-
- /**
- * Sets wrap type for textarea element
- *
- * @param string $wrap Wrap type
- * @since 1.0
- * @access public
- * @return void
- */
- function setWrap($wrap)
- {
- $this->updateAttributes(array('wrap' => $wrap));
- } //end func setWrap
-
- // }}}
- // {{{ setRows()
-
- /**
- * Sets height in rows for textarea element
- *
- * @param string $rows Height expressed in rows
- * @since 1.0
- * @access public
- * @return void
- */
- function setRows($rows)
- {
- $this->updateAttributes(array('rows' => $rows));
- } //end func setRows
-
- // }}}
- // {{{ setCols()
-
- /**
- * Sets width in cols for textarea element
- *
- * @param string $cols Width expressed in cols
- * @since 1.0
- * @access public
- * @return void
- */
- function setCols($cols)
- {
- $this->updateAttributes(array('cols' => $cols));
- } //end func setCols
-
- // }}}
- // {{{ toHtml()
-
- /**
- * Returns the textarea element in HTML
- *
- * @since 1.0
- * @access public
- * @return string
- */
- function toHtml()
- {
- if ($this->_flagFrozen) {
- return $this->getFrozenHtml();
- } else {
- return $this->_getTabs() .
- '<textarea' . $this->_getAttrString($this->_attributes) . '>' .
- // because we wrap the form later we don't want the text indented
- preg_replace("/(\r\n|\n|\r)/", '
', htmlspecialchars($this->_value)) .
- '</textarea>';
- }
- } //end func toHtml
-
- // }}}
- // {{{ getFrozenHtml()
-
- /**
- * Returns the value of field without HTML tags (in this case, value is changed to a mask)
- *
- * @since 1.0
- * @access public
- * @return string
- */
- function getFrozenHtml()
- {
- $value = htmlspecialchars($this->getValue());
- if ($this->getAttribute('wrap') == 'off') {
- $html = $this->_getTabs() . '<pre>' . $value."</pre>\n";
- } else {
- $html = nl2br($value)."\n";
- }
- return $html . $this->_getPersistantData();
- } //end func getFrozenHtml
-
- // }}}
-
-} //end class HTML_QuickForm_textarea
-?>
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * utility functions
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Chuck Burgess <ashnazg@php.net>
- * @copyright 2001-2018 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Provides a collection of static methods for array manipulation.
- *
- * (courtesy of CiviCRM project (https://civicrm.org/)
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Chuck Burgess <ashnazg@php.net>
- * @version Release: 3.2.16
- * @since 3.2
- */
-class HTML_QuickForm_utils
-{
- /**
- * Get a single value from an array-tree.
- *
- * @param array $values Ex: ['foo' => ['bar' => 123]].
- * @param array $path Ex: ['foo', 'bar'].
- * @param mixed $default
- * @return mixed Ex 123.
- *
- * @access public
- * @static
- */
- function pathGet($values, $path, $default = NULL) {
- foreach ($path as $key) {
- if (!is_array($values) || !isset($values[$key])) {
- return $default;
- }
- $values = $values[$key];
- }
- return $values;
- }
-
- /**
- * Check if a key isset which may be several layers deep.
- *
- * This is a helper for when the calling function does not know how many layers deep
- * the path array is so cannot easily check.
- *
- * @param array $values
- * @param array $path
- * @return bool
- *
- * @access public
- * @static
- */
- function pathIsset($values, $path) {
- foreach ($path as $key) {
- if (!is_array($values) || !isset($values[$key])) {
- return FALSE;
- }
- $values = $values[$key];
- }
- return TRUE;
- }
-
- /**
- * Set a single value in an array tree.
- *
- * @param array $values Ex: ['foo' => ['bar' => 123]].
- * @param array $pathParts Ex: ['foo', 'bar'].
- * @param mixed $value Ex: 456.
- * @return void
- *
- * @access public
- * @static
- */
- function pathSet(&$values, $pathParts, $value) {
- $r = &$values;
- $last = array_pop($pathParts);
- foreach ($pathParts as $part) {
- if (!isset($r[$part])) {
- $r[$part] = array();
- }
- $r = &$r[$part];
- }
- $r[$last] = $value;
- }
-
- /**
- * Check if a key isset which may be several layers deep.
- *
- * This is a helper for when the calling function does not know how many layers deep the
- * path array is so cannot easily check.
- *
- * @param array $array
- * @param array $path
- * @return bool
- *
- * @access public
- * @static
- */
- function recursiveIsset($array, $path) {
- return self::pathIsset($array, $path);
- }
-
- /**
- * Check if a key isset which may be several layers deep.
- *
- * This is a helper for when the calling function does not know how many layers deep the
- * path array is so cannot easily check.
- *
- * @param array $array
- * @param array $path An array of keys,
- * e.g [0, 'bob', 8] where we want to check if $array[0]['bob'][8]
- * @param mixed $default Value to return if not found.
- * @return bool
- *
- * @access public
- * @static
- */
- function recursiveValue($array, $path, $default = NULL) {
- return self::pathGet($array, $path, $default);
- }
-
- /**
- * Append the value to the array using the key provided.
- *
- * e.g if value is 'llama' & path is [0, 'email', 'location'] result will be
- * [0 => ['email' => ['location' => 'llama']]
- *
- * @param $path
- * @param $value
- * @param array $source
- * @return array
- *
- * @access public
- * @static
- */
- function recursiveBuild($path, $value, $source = array()) {
- self::pathSet($source, $path, $value);
- return $source;
- }
-}
-?>
\ No newline at end of file
+++ /dev/null
-<?php
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
-/**
- * Class for HTML 4.0 <button> element
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.01 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_01.txt If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Alexey Borzov <avb@php.net>
- * @copyright 2001-2011 The PHP Group
- * @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTML_QuickForm
- */
-
-/**
- * Base class for form elements
- */
-require_once 'HTML/QuickForm/element.php';
-
-/**
- * Class for HTML 4.0 <button> element
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Alexey Borzov <avb@php.net>
- * @version Release: 3.2.16
- * @since 3.2.3
- */
-class HTML_QuickForm_xbutton extends HTML_QuickForm_element
-{
- /**
- * Contents of the <button> tag
- * @var string
- * @access private
- */
- var $_content;
-
- /**
- * Class constructor
- *
- * @param string Button name
- * @param string Button content (HTML to add between <button></button> tags)
- * @param mixed Either a typical HTML attribute string or an associative array
- * @access public
- */
- function HTML_QuickForm_xbutton($elementName = null, $elementContent = null, $attributes = null)
- {
- $this->HTML_QuickForm_element($elementName, null, $attributes);
- $this->setContent($elementContent);
- $this->setPersistantFreeze(false);
- $this->_type = 'xbutton';
- }
-
-
- function toHtml()
- {
- return '<button' . $this->getAttributes(true) . '>' . $this->_content . '</button>';
- }
-
-
- function getFrozenHtml()
- {
- return $this->toHtml();
- }
-
-
- function freeze()
- {
- return false;
- }
-
-
- function setName($name)
- {
- $this->updateAttributes(array(
- 'name' => $name
- ));
- }
-
-
- function getName()
- {
- return $this->getAttribute('name');
- }
-
-
- function setValue($value)
- {
- $this->updateAttributes(array(
- 'value' => $value
- ));
- }
-
-
- function getValue()
- {
- return $this->getAttribute('value');
- }
-
-
- /**
- * Sets the contents of the button element
- *
- * @param string Button content (HTML to add between <button></button> tags)
- */
- function setContent($content)
- {
- $this->_content = $content;
- }
-
-
- function onQuickFormEvent($event, $arg, &$caller)
- {
- if ('updateValue' != $event) {
- return parent::onQuickFormEvent($event, $arg, $caller);
- } else {
- $value = $this->_findValue($caller->_constantValues);
- if (null === $value) {
- $value = $this->_findValue($caller->_defaultValues);
- }
- if (null !== $value) {
- $this->setValue($value);
- }
- }
- return true;
- }
-
-
- /**
- * Returns a 'safe' element's value
- *
- * The value is only returned if the button's type is "submit" and if this
- * particlular button was clicked
- */
- function exportValue(&$submitValues, $assoc = false)
- {
- if ('submit' == $this->getAttribute('type')) {
- return $this->_prepareValue($this->_findValue($submitValues), $assoc);
- } else {
- return null;
- }
- }
-}
-?>
+++ /dev/null
-<?php
-session_start();
-require_once 'HTML/QuickForm.php';
-require_once 'HTML/QuickForm/DHTMLRulesTableless.php';
-require_once 'HTML/QuickForm/Renderer/Tableless.php';
-
-function process_data ($values) {
- echo '<h1>Thank you</h1>';
- echo 'Your report has been submitted';
- $email_body = 'OpenStreetMap - Claim of Copyright Infringement form:'."\n\n";
- $email_body .= 'Automated Email - Form Posted.'."\n\n";
- $email_body .= print_r($values, true);
- $reply_address = $values['name_first'].' '.$values['name_last'].' <'.$values['email'].'>';
- $email_body .= 'Formatted address: '.$reply_address."\n\n";
- $email_header = 'From: OSMF Copyright Form <dmca@osmfoundation.org>' . "\r\n" . 'Content-Type: text/plain; charset="utf-8"';
- mail('dmca@osmfoundation.org','OSM Claim of Copyright Infringement', $email_body, $email_header, '-fdmca@osmfoundation.org');
-}
-?>
-<!DOCTYPE html>
-<html>
-<head>
-<title>OpenStreetMap Legal - Claim of Copyright Infringement</title>
-<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
- <link rel="stylesheet" type="text/css" href="/style.css" />
-</head>
-<body>
-<div class="regForm">
-<?php
-// Instantiate the HTML_QuickForm object
-$form = new HTML_QuickForm_DHTMLRulesTableless('osm_legal_claim_of_copyright');
-$renderer = new HTML_QuickForm_Renderer_Tableless();
-
-$form->addElement('header', null, 'OpenStreetMap: Claim of Copyright Infringement');
-
-$form->addElement('static', null, '<p>To file a copyright infringement notification with us, you will need to send a written communication that includes the following (please consult your legal counsel or see Section 512(c)(3) of the Digital Millennium Copyright Act to confirm these requirements):</p>
-<ul><li> A physical or electronic signature of a person authorized to act on behalf of the owner of an exclusive right that is allegedly infringed.
-<li>Identification of the copyrighted work claimed to have been infringed or, if multiple copyrighted works at a single online site are covered by a single notification, a representative list of such works at that site.
-<li>Identification of the material that is claimed to be infringing or to be the subject of infringing activity and that is to be removed or access to which is to be disabled, and information reasonably sufficient to permit the service provider to locate the material. Providing URLs in the body of an email is the best way to help us locate content quickly.
-<li>Information reasonably sufficient to permit the service provider to contact the complaining party, such as an address, telephone number, and, if available, an electronic mail address at which the complaining party may be contacted.
-<li>A statement that the complaining party has a good faith belief that use of the material in the manner complained of is not authorized by the copyright owner, its agent, or the law.
-<li>A statement that the information in the notification is accurate and, under penalty of perjury, that the complaining party is authorized to act on behalf of the owner of an exclusive right that is allegedly infringed.
-</ul><p>To expedite our ability to process your request, such written notice should be sent to our designated agent via our online copyright complaint form below.</p>
-<p>This form is only for cases where you believe that material on OpenStreetMap\'s websites or in its geodata database infringes your copyright or that of your clients. For example, you claim someone has copied material from a map belonging to you.</p>
-<p>If you have come here for reporting map inaccuracies, privacy issues or another reason, <a href="https://wiki.osmfoundation.org/wiki/Licence_and_Legal_FAQ/Takedown_procedure/When_To_Use_The_Form">Read here</a>.</p>');
-
-$form->addElement('text', 'url', 'URL of Allegedly Infringing Material', array('size' => 50, 'maxlength' => 255));
-$form->addRule('url', 'Please enter URL of Allegedly Infringing Material', 'required', null, 'client');
-
-$form->addElement('textarea', 'work', 'Describe the work allegedly infringed. For example, which map has been copied and what specifically has been copied.', array('rows' => 20, 'cols' => 70));
-$form->addRule('work', 'Please describe the work allegedly infringed', 'required', null, 'client');
-
-$form->addElement('text', 'territory', 'Territories where infringement occurred', array('size' => 50, 'maxlength' => 255));
-$form->addRule('territory', 'Please enter the territories where infringement occurred', 'required', null, 'client');
-
-$form->addElement('text', 'name_first', 'First Name', array('size' => 50, 'maxlength' => 255));
-$form->addRule('name_first', 'Please enter your First Name', 'required', null, 'client');
-
-$form->addElement('text', 'name_last', 'Last Name', array('size' => 50, 'maxlength' => 255));
-$form->addRule('name_last', 'Please enter your Last Name', 'required', null, 'client');
-
-
-$form->addElement('text', 'company', 'Company Name', array('size' => 50, 'maxlength' => 255));
-$form->addElement('text', 'company_tile', 'Title/Position');
-
-$form->addElement('text', 'address', 'Street Address');
-$form->addRule('address', 'Please enter Street Address', 'required', null, 'client');
-
-$form->addElement('text', 'city', 'City', array('size' => 50, 'maxlength' => 255));
-$form->addRule('city', 'Please enter City', 'required', null, 'client');
-
-$form->addElement('text', 'state', 'State/Province', array('size' => 50, 'maxlength' => 255));
-$form->addElement('text', 'postal_code', 'Zip/Postal Code', array('size' => 50, 'maxlength' => 255));
-
-$form->addElement('text', 'country', 'Country', array('size' => 50, 'maxlength' => 255));
-$form->addRule('country', 'Please enter Country', 'required', null, 'client');
-
-$form->addElement('text', 'phone_number', 'Phone Number', array('size' => 50, 'maxlength' => 255));
-$form->addRule('phone_number', 'Please enter Phone Number', 'required', null, 'client');
-
-$form->addElement('text', 'mobile_number', 'Mobile Number', array('size' => 50, 'maxlength' => 255));
-
-$form->addElement('text', 'email', 'Email Address', array('size' => 50, 'maxlength' => 255));
-$form->addRule('email', 'Please enter Email Address', 'required', null, 'client');
-$form->addRule('email', 'Please enter a valid Email Address', 'email', null, 'client');
-
-$form->addElement('text', 'fax', 'Fax', array('size' => 50, 'maxlength' => 255));
-
-$complaint_options = array();
-$complaint_options[] = &HTML_QuickForm::createElement('checkbox', '1_of_4_owner_or_authorised', null, 'I am the owner, or an agent authorized to act on behalf of the owner, of an exclusive right that is allegedly infringed.');
-$complaint_options[] = &HTML_QuickForm::createElement('checkbox', '2_of_4_good_faith', null, 'I have a good faith belief that the use of the material in the manner complained of is not authorized by the copyright owner, its agent, or the law; and');
-$complaint_options[] = &HTML_QuickForm::createElement('checkbox', '3_of_4_accurate', null, 'This notification is accurate.');
-$complaint_options[] = &HTML_QuickForm::createElement('checkbox', '4_of_4_not_misrepresent', null, 'I acknowledge that under Section 512(f) any person who knowingly materially misrepresents that material or activity is infringing may be subject to liability for damages.');
-
-$form->addGroup($complaint_options, 'complaint_confirm', 'By checking the following boxes, I state UNDER PENALTY OF PERJURY that (choose all of the options)', '<br />');
-
-$form->addElement('text', 'signature', 'Typing your full name in this box will act as your digital signature.', array('size' => 25, 'maxlength' => 255));
-$form->addRule('signature', 'Field is required', 'required', null, 'client');
-
-$form->addElement('submit', null, 'Send');
-
-$form->removeAttribute('name');
-$form->getValidationScript();
-
-if ($form->validate()) {
- // Do some stuff
- $form->freeze();
- $form->process('process_data', false);
-
-} else {
- // Output the form
- $form->accept($renderer);
- echo $renderer->toHtml();
-}
-?>
-</div>
-</body>
-</html>
+++ /dev/null
-User-agent: *
-Disallow: /
+++ /dev/null
-/* Forms
------------------------------------------------------------------------------*/
-
-.regForm {
- padding: 0;
- margin: 0;
- max-width: 730px;
-}
-
-.regForm fieldset {
- padding: 15px;
- border: 1px solid #747577;
- margin-top: 20px;
-}
-
-.regForm legend {
- padding: 0px 10px 0px 5px;
- font-size: 1.1em;
- color: #000000;
-}
-
-#regFormHeader {
- border-style: none;
- padding: 0px;
- margin: 10px 0px 2px 0px;
- font-size: 1.2em;
-}
-
-#regFormSubHeader {
- font-size: 1em;
- padding: 0px;
- margin: 0px 0px 2px 0px;
- border: none;
-}
-
-.regForm fieldset .inputbox {
- padding:0!important;
- padding-top:0!important;
- padding-bottom:0!important;
-}
-
-.regForm input {
- color: #747577;
- padding: 6px;
- margin-bottom: 0px;
- margin-top: 0px;
-
- -webkit-border-radius:5px;
- -moz-border-radius:5px;
- border-radius: 5px;
- border:1px solid #ccc;
- -webkit-box-shadow: 0 2px 4px rgba(0,0,0,0.5);
- -moz-box-shadow: 0 2px 4px rgba(0,0,0,0.5);
- box-sizing: border-box;
- -moz-box-sizing: border-box;
- -webkit-box-sizing: border-box;
-}
-
-.regForm textarea {
- color: #747577;
- padding: 6px;
- margin-bottom: 5px;
-
- -webkit-border-radius:5px;
- -moz-border-radius:5px;
- border-radius: 5px;
- border:1px solid #ccc;
- -webkit-box-shadow: 0 2px 4px rgba(0,0,0,0.5);
- -moz-box-shadow: 0 2px 4px rgba(0,0,0,0.5);
- box-sizing: border-box;
- -moz-box-sizing: border-box;
- -webkit-box-sizing: border-box;
-}
-
-.regForm select {
- color: #747577;
- padding: 6px;
- margin-bottom: 5px;
-
- -webkit-border-radius:5px;
- -moz-border-radius:5px;
- border-radius: 5px;
- border:1px solid #ccc;
- -webkit-box-shadow: 0 2px 4px rgba(0,0,0,0.5);
- -moz-box-shadow: 0 2px 4px rgba(0,0,0,0.5);
- box-sizing: border-box;
- -moz-box-sizing: border-box;
- -webkit-box-sizing: border-box;
-}
-
-.regForm button {
- padding: 0px 5px 0px 0px;
-}
-
-.regForm ol > li {
- list-style: none;
- background-image: none;
- padding: 3px 0px 5px 0px;
- border-top: 1px solid #f0f0f0;
- color: #747577;
-}
-
-.regForm li.formList-top {
- border-top: none;
- font-size: .8em;
- padding: 10px 0px;
-}
-
-.regForm li.formList {
- font-size: .8em;
- padding: 10px 0px;
-}
-
-.regForm li.opt {
- border-top: 0;
- display: none;
-}
-
-.elementItem {
- padding: 0;
- display: block;
- clear: left;
- border-style: none;
-}
-
-.elementItemGroup {
- padding: 0;
- margin: 0;
- display: block;
- border-top: 2px solid #C0C0C0;
-}
-
-li.elementItemEnd {
- padding: 0;
- display: block;
- clear: left;
- border-style: none;
-}
-
-.elementGroup {
- padding: 0;
-}
-
-.elementGroup ul {
- float: left;
- margin-left: 0px;
- margin-top: 0px;
- padding: 0;
-}
-
-.elementGroup li {
- margin: 0;
- margin-left: 0px;
- margin-top: 2px;
- margin-right: 5px;
- padding: 2px 2px 2px 0px;
- border-style: none;
- min-width: 255px;
- list-style: none;
-}
-
-.elementGroupEnd {
- border-style: none;
- margin: 0;
- padding: 0;
- height: 1px;
-}
-
-.regForm ol {
- margin: 0px;
- padding: 0px;
-}
-
-.regForm p {
- font-size: 1.2em;
-}
-
-.regForm .error {
- color: #ff0000;
- font-weight: bold;
-}
-
-.regForm .required {
- color: #ff0000;
-}
-
-.regForm label.element {
- color: #000000;
- padding: 0px 5px 2px 0px;
- margin: 0px;
-}
-
-.regForm div.element {
- color: #747577;
- padding: 1px 0px 0px 0px;
-}
-
-.regForm div.element label {
- padding: 0px 15px 0px 4px;
-}
-
-.regForm input[type="submit"] {
-/* border: 1px solid #f0f0f0;*/
- color: #747577;
- margin: 10px 0px;
-}
-
-.regForm input[type="submit"]:hover {
- color: #CCCCCC;
- text-decoration: none;
-}
-
-.regForm option {
- color: #747577;
-}
-
-.regForm .reqnote {
- font-size: 90%;
- color: #747577;
- font-weight: bold;
-}
-
-.regForm input[type="radio"] {
- border: 0;
-}
-
version "1.0.0"
supports "ubuntu"
-depends "apache"
-depends "php"
+depends "podman"
# limitations under the License.
#
-include_recipe "apache"
-include_recipe "php::fpm"
+include_recipe "podman::apache"
-apache_module "proxy"
-apache_module "proxy_fcgi"
-
-directory "/srv/dmca.openstreetmap.org" do
- owner "root"
- group "root"
- mode "755"
-end
-
-remote_directory "/srv/dmca.openstreetmap.org/html" do
- source "html"
- owner "root"
- group "root"
- mode "755"
- files_owner "root"
- files_group "root"
- files_mode "644"
-end
-
-ssl_certificate "dmca.openstreetmap.org" do
- domains ["dmca.openstreetmap.org", "dmca.osm.org"]
- notifies :reload, "service[apache2]"
-end
-
-php_fpm "dmca.openstreetmap.org" do
- php_admin_values "open_basedir" => "/srv/dmca.openstreetmap.org/html/:/usr/share/php/:/tmp/",
- "disable_functions" => "exec,shell_exec,system,passthru,popen,proc_open"
- prometheus_port 11201
-end
-
-apache_site "dmca.openstreetmap.org" do
- template "apache.erb"
- directory "/srv/dmca.openstreetmap.org"
- variables :aliases => ["dmca.osm.org"]
+podman_site "dmca.openstreetmap.org" do
+ image "ghcr.io/openstreetmap/dmca-website:latest"
+ aliases ["dmca.osm.org"]
end
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-<VirtualHost *:80>
- ServerName <%= @name %>
-<% @aliases.each do |alias_name| -%>
- ServerAlias <%= alias_name %>
-<% end -%>
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
- ErrorLog /var/log/apache2/<%= @name %>-error.log
-
- RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
- RedirectPermanent / https://<%= @name %>/
-</VirtualHost>
-<% unless @aliases.empty? -%>
-
-<VirtualHost *:443>
- ServerName <%= @aliases.first %>
-<% @aliases.drop(1).each do |alias_name| -%>
- ServerAlias <%= alias_name %>
-<% end -%>
- ServerAdmin webmaster@openstreetmap.org
-
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
- SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
-
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
- ErrorLog /var/log/apache2/<%= @name %>-error.log
-
- RedirectPermanent / https://<%= @name %>/
-</VirtualHost>
-<% end -%>
-
-<VirtualHost *:443>
- ServerName <%= @name %>
- ServerAdmin webmaster@openstreetmap.org
-
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
- SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
-
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
- ErrorLog /var/log/apache2/<%= @name %>-error.log
-
- DocumentRoot <%= @directory %>/html
-
- Options -Indexes
-</VirtualHost>
-
-<Directory <%= @directory %>/html>
- Require all granted
-
- <FilesMatch ".+\.ph(ar|p|tml)$">
- SetHandler "proxy:unix:/run/php/<%= @name %>.sock|fcgi://127.0.0.1"
- </FilesMatch>
-</Directory>
depends "accounts"
depends "apache"
depends "git"
+depends "systemd"
libwww-perl
libxml-treebuilder-perl
libxml-writer-perl
+ libyaml-perl
libyaml-libyaml-perl
lockfile-progs
]
-remote_file "/usr/local/bin/dnscontrol" do
- action :create
- source "https://github.com/StackExchange/dnscontrol/releases/download/v3.8.1/dnscontrol-Linux"
+cache_dir = Chef::Config[:file_cache_path]
+
+dnscontrol_version = "4.8.1"
+
+dnscontrol_arch = if arm?
+ "arm64"
+ else
+ "amd64"
+ end
+
+remote_file "#{cache_dir}/dnscontrol-#{dnscontrol_version}.deb" do
+ source "https://github.com/StackExchange/dnscontrol/releases/download/v#{dnscontrol_version}/dnscontrol-#{dnscontrol_version}.#{dnscontrol_arch}.deb"
owner "root"
group "root"
- mode "755"
+ mode "644"
+ backup false
+end
+
+dpkg_package "dnscontrol" do
+ source "#{cache_dir}/dnscontrol-#{dnscontrol_version}.deb"
+ version "#{dnscontrol_version}"
end
directory "/srv/dns.openstreetmap.org" do
variables :passwords => passwords
end
+template "/var/lib/dns/include/geo.js" do
+ source "geo.js.erb"
+ owner "git"
+ group "git"
+ mode "440"
+ variables :geoservers => geoservers
+ only_if { ::Dir.exist?("/var/lib/dns/include") }
+end
+
cookbook_file "#{node[:dns][:repository]}/hooks/post-receive" do
source "post-receive"
owner "git"
variables :passwords => passwords, :geoservers => geoservers
end
-cron_d "dns" do
- minute "*/3"
+systemd_service "dns-check" do
+ description "Rebuild DNS zones with GeoDNS changes"
+ exec_start "/usr/local/bin/dns-check"
user "git"
- command "/usr/local/bin/dns-check"
- mailto "admins@openstreetmap.org"
+ runtime_max_sec 90
+ sandbox :enable_network => true
+ proc_subset "all"
+ read_write_paths "/var/lib/dns"
+end
+
+systemd_timer "dns-check" do
+ description "Rebuild DNS zones with GeoDNS changes"
+ on_boot_sec "3m"
+ on_unit_active_sec "3m"
+end
+
+service "dns-check.timer" do
+ action [:enable, :start]
end
<% end -%>
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
RedirectPermanent / https://<%= @name %>/
SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
DocumentRoot <%= @directory %>/html
{
"gandi_v5": {
+ "TYPE": "GANDI_V5",
"apikey": "<%= @passwords["gandi"] %>",
"sharing_id": "7028b616-ba65-11e7-8343-00163ec31f40"
},
"cloudflare": {
+ "TYPE": "CLOUDFLAREAPI",
"accountid": "049c95aba02c95fc1e78a9d255282e0f",
"accountname": "OpenStreetMap",
"apitoken": "<%= @passwords["cloudflare"] %>"
git pull -q
-make --jobs update
+make --jobs check update
lockfile-remove update
--- /dev/null
+var GEO_NS_RECORDS = [
+<% @geoservers.each do |server| -%>
+ NS("geo", "<%= server %>."),
+<% end -%>
+];
+++ /dev/null
-# Add the docker APT source
-default[:apt][:sources] = node[:apt][:sources] | ["docker"]
version "1.0.0"
supports "ubuntu"
depends "apt"
+depends "systemd"
# limitations under the License.
#
-include_recipe "apt"
+include_recipe "apt::docker"
package %w[
docker-ce
docker-ce-cli
containerd.io
+ docker-compose-plugin
]
directory "/etc/docker" do
mode "644"
end
+service "containerd" do
+ action [:enable, :start]
+ subscribes :restart, "template[/etc/docker/daemon.json]"
+end
+
service "docker" do
action [:enable, :start]
subscribes :restart, "template[/etc/docker/daemon.json]"
- not_if { ENV["TEST_KITCHEN"] }
+end
+
+systemd_service "docker-system-prune" do
+ description "Cleanup up unused docker images and containers"
+ after ["docker.service"]
+ wants ["docker.service"]
+ user "root"
+ exec_start "/usr/bin/docker system prune --all --force"
+ sandbox :enable_network => true
+ memory_deny_write_execute false
+ restrict_address_families "AF_UNIX"
+end
+
+systemd_timer "docker-system-prune" do
+ description "Cleanup up unused docker images and containers"
+ on_boot_sec "2h"
+ on_unit_active_sec "7d"
+ randomized_delay_sec "4h"
+end
+
+service "docker-system-prune.timer" do
+ action [:enable, :start]
end
"log-opts": {
"max-size": "100m"
},
- "storage-driver": "overlay2"
+ "storage-driver": "overlay2",
+ "experimental": true,
+ "ipv6": true,
+ "ip6tables": true,
+ "fixed-cidr-v6": "fd9e:d0ce:beef::/48"
}
+++ /dev/null
-# Donate Cookbook
-
-This cookbook installs the donate.openstreetmap.org site
+++ /dev/null
-# Enable the "donate" role
-default[:accounts][:users][:donate][:status] = :role
+++ /dev/null
-#
-# Cookbook:: donate
-# Recipe:: default
-#
-# Copyright:: 2016, OpenStreetMap Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-include_recipe "accounts"
-include_recipe "apache"
-include_recipe "git"
-include_recipe "mysql"
-include_recipe "php::fpm"
-
-package %w[
- php-cli
- php-curl
- php-mysql
- php-gd
-]
-
-apache_module "headers"
-apache_module "proxy"
-apache_module "proxy_fcgi"
-
-passwords = data_bag_item("donate", "passwords")
-
-database_password = passwords["database"]
-
-mysql_user "donate@localhost" do
- password database_password
-end
-
-mysql_database "donate" do
- permissions "donate@localhost" => :all
-end
-
-directory "/srv/donate.openstreetmap.org" do
- owner "donate"
- group "donate"
- mode "755"
-end
-
-git "/srv/donate.openstreetmap.org" do
- action :sync
- repository "https://github.com/osmfoundation/donation-drive.git"
- depth 1
- user "donate"
- group "donate"
-end
-
-directory "/srv/donate.openstreetmap.org/data" do
- owner "donate"
- group "donate"
- mode "755"
-end
-
-template "/srv/donate.openstreetmap.org/scripts/db-connect.inc.php" do
- source "db-connect.inc.php.erb"
- owner "root"
- group "donate"
- mode "644"
- variables :passwords => passwords
-end
-
-ssl_certificate "donate.openstreetmap.org" do
- domains ["donate.openstreetmap.org", "donate.openstreetmap.com",
- "donate.openstreetmap.net", "donate.osm.org"]
- notifies :reload, "service[apache2]"
-end
-
-php_fpm "donate.openstreetmap.org" do
- php_admin_values "open_basedir" => "/srv/donate.openstreetmap.org/:/usr/share/php/:/tmp/",
- "disable_functions" => "exec,shell_exec,system,passthru,popen,proc_open"
- prometheus_port 11101
-end
-
-apache_site "donate.openstreetmap.org" do
- template "apache.erb"
-end
-
-cron_d "osmf-donate" do
- minute "*/2"
- user "donate"
- command "cd /srv/donate.openstreetmap.org/scripts/; /usr/bin/php /srv/donate.openstreetmap.org/scripts/update_csv_donate2016.php"
-end
-
-template "/etc/cron.daily/osmf-donate-backup" do
- source "backup.cron.erb"
- owner "root"
- group "root"
- mode "750"
- variables :passwords => passwords
-end
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-<% [80, 443].each do |port| -%>
-<VirtualHost *:<%= port %>>
-
- ServerName donate.openstreetmap.org
- ServerAlias donate.openstreetmap.com
- ServerAlias donate.openstreetmap.net
- ServerAlias donate.osm.org
-
- ServerAdmin webmaster@openstreetmap.org
-
-<% if port == 80 -%>
- RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
- RedirectPermanent / https://donate.openstreetmap.org/
-<% end -%>
-<% if port == 443 -%>
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/donate.openstreetmap.org.pem
- SSLCertificateKeyFile /etc/ssl/private/donate.openstreetmap.org.key
-<% end -%>
-
- CustomLog /var/log/apache2/donate.openstreetmap.org-access.log combined
- ErrorLog /var/log/apache2/donate.openstreetmap.org-error.log
-
- Options -Indexes
-
- DocumentRoot /srv/donate.openstreetmap.org
-
- # Alias Dynamic Content to data folder to avoid serving dummy git content
- Alias /donors-eur.csv /srv/donate.openstreetmap.org/data/donors-eur.csv
- Alias /donors.csv /srv/donate.openstreetmap.org/data/donors.csv
-
- # Redirect previous compaigns to homepage
- Redirect permanent /domain https://donate.openstreetmap.org/
- Redirect permanent /memorial https://donate.openstreetmap.org/
- Redirect permanent /server2011 https://donate.openstreetmap.org/
- Redirect permanent /server2013 https://donate.openstreetmap.org/
- Redirect permanent /server2015 https://donate.openstreetmap.org/
-
- <Directory /srv/donate.openstreetmap.org>
- Require all granted
-
- <FilesMatch ".+\.ph(ar|p|tml)$">
- SetHandler "proxy:unix:/run/php/donate.openstreetmap.org.sock|fcgi://127.0.0.1"
- </FilesMatch>
- </Directory>
-
- <Directory /srv/donate.openstreetmap.org/scripts>
- Require all denied
- </Directory>
-
- <Directory ~ "\.svn">
- Require all denied
- </Directory>
-
- <Directory ~ "\.git">
- Require all denied
- </Directory>
-
- <Files ~ "~$">
- Require all denied
- </Files>
-
- # Enable deflate compression on .csv files if possible
- <IfModule mod_deflate.c>
- DeflateCompressionLevel 9
- AddOutputFilterByType DEFLATE text/csv
- </IfModule>
-
- <IfModule mod_expires.c>
- ExpiresDefault "access plus 15 minutes"
- ExpiresByType text/html "access plus 5 minutes"
- ExpiresByType text/csv "access plus 1 minute"
- </IfModule>
-</VirtualHost>
-
-<% end -%>
+++ /dev/null
-#!/bin/sh
-
-# DO NOT EDIT - This file is being maintained by Chef
-
-T=$(mktemp -d -t -p /var/tmp osm-donate.XXXXXXXXXX)
-D=$(date +%Y-%m-%d)
-B=osm-donate-$D.tar.gz
-
-mkdir $T/osm-donate-$D
-echo '[mysqldump]' > $T/mysqldump.opts
-echo 'user=donate' >> $T/mysqldump.opts
-echo 'password=<%= @passwords["database"] %>' >> $T/mysqldump.opts
-mysqldump --defaults-file=$T/mysqldump.opts --opt --no-tablespaces donate > $T/osm-donate-$D/osm-donate.sql
-ln -s /srv/donate.openstreetmap.org $T/osm-donate-$D/www
-
-export RSYNC_RSH="ssh -ax"
-
-nice tar --create --dereference --directory=$T osm-donate-$D | nice gzip --rsyncable -9 > $T/$B
-nice rsync --preallocate --fuzzy $T/$B backup::backup
-
-rm -rf $T
+++ /dev/null
-<?php
-$_DB_H = new mysqli('localhost','donate','<%= @passwords['database'] %>','donate');
-if ($_DB_H->connect_errno) {
- die('DB Connect Error: ' . $_DB_H->connect_errno);
-}
-$_DB_H->report_mode = MYSQLI_REPORT_ERROR;
-$_DB_H->query('set @@sql_mode = \'\'');
-$_DB_H->query('SET NAMES \'utf8\'');
default[:elasticsearch][:cluster][:routing][:allocation][:disk][:watermark][:high] = "90%"
default[:elasticsearch][:cluster][:routing][:allocation][:disk][:watermark][:flood_stage] = "95%"
default[:elasticsearch][:path][:data] = "/var/lib/elasticsearch"
-
-default[:apt][:sources] |= ["elasticsearch#{node[:elasticsearch][:version]}"]
version "1.0.0"
supports "ubuntu"
depends "apt"
+depends "prometheus"
# limitations under the License.
#
-include_recipe "apt"
+include_recipe "prometheus"
+
+case node[:elasticsearch][:version]
+when "6.x" then include_recipe "apt::elasticsearch6"
+when "7.x" then include_recipe "apt::elasticsearch7"
+when "8.x" then include_recipe "apt::elasticsearch8"
+end
package "default-jre-headless"
package "elasticsearch"
action [:enable, :start]
supports :status => true, :restart => true
end
+
+prometheus_exporter "elasticsearch" do
+ port 9114
+end
default[:exim][:daemon_smtp_ports] = [25]
default[:exim][:trusted_users] = []
default[:exim][:queue_run_max] = 1
+default[:exim][:smtp_accept_max] = 20
default[:exim][:smarthost_name] = nil
default[:exim][:smarthost_via] = "mail.openstreetmap.org:26"
default[:exim][:routes] = {}
This is an automated response to your email, which was sent to an
unattended address.
-If you are having technical problems with the forums then please
-contact support@openstreetmap.org for assistance.
+You can not reply to this email, please use the
+community.openstreetmap.org web site instead.
Thank you,
unattended address.
If you were trying to confirm your email address after signing
-up for an account, or after changing your email address, then you
+up for an account, or after changing your email address, then you
should click on the link in the original email you received.
If you need help using OpenStreetMap then you should try our
-question and answer site:
+community site:
- https://help.openstreetmap.org/
+ https://community.openstreetmap.org/
If you are having technical problems with the web site then please
contact support@openstreetmap.org for assistance.
supports "ubuntu"
depends "accounts"
depends "apache"
-depends "munin"
depends "networking"
depends "prometheus"
depends "ssl"
# limitations under the License.
#
-include_recipe "munin"
include_recipe "networking"
include_recipe "prometheus"
exim4
openssl
ssl-cert
+ mailutils
]
package "exim4-daemon-heavy" do
only_if { ::File.exist?("/var/run/clamav/clamd.ctl") }
end
+group "Debian-exim" do
+ action :modify
+ members "clamav"
+ append true
+ only_if { ::File.exist?("/var/run/clamav/clamd.ctl") }
+end
+
group "ssl-cert" do
action :modify
members "Debian-exim"
relay_from_hosts = node[:exim][:relay_from_hosts]
if node[:exim][:smarthost_name]
- search(:node, "roles:gateway") do |gateway|
- allowed_ips = gateway.interfaces(:role => :internal).map do |interface|
- "#{interface[:network]}/#{interface[:prefix]}"
- end
-
- node.default[:networking][:wireguard][:peers] << {
- :public_key => gateway[:networking][:wireguard][:public_key],
- :allowed_ips => allowed_ips,
- :endpoint => "#{gateway.name}:51820"
- }
- end
-
- search(:node, "exim_smarthost_via:#{node[:exim][:smarthost_name]}\\:*").each do |host|
+ search(:node, "exim_smarthost_via:*?").each do |host|
relay_from_hosts |= host.ipaddresses(:role => :external)
end
mode "644"
end
+file "/etc/exim4/blocked-sender-domains" do
+ owner "root"
+ group "Debian-exim"
+ mode "644"
+end
+
+file "/etc/exim4/detaint" do
+ owner "root"
+ group "Debian-exim"
+ mode "644"
+ content "*"
+end
+
if node[:exim][:dkim_selectors]
keys = data_bag_item("exim", "dkim")
purge true
end
-munin_plugin "exim_mailqueue"
-munin_plugin "exim_mailstats"
+template "/etc/mail.rc" do
+ source "mail.rc.erb"
+ owner "root"
+ group "root"
+ mode "644"
+end
prometheus_exporter "exim" do
port 9636
+ user "Debian-exim"
+ protect_proc "default"
end
if node[:exim][:smarthost_name]
- node[:exim][:daemon_smtp_ports].each do |port|
- firewall_rule "accept-inbound-smtp-#{port}" do
- action :accept
- source "net"
- dest "fw"
- proto "tcp:syn"
- dest_ports port
- source_ports "1024:"
- end
+ firewall_rule "accept-inbound-smtp" do
+ action :accept
+ context :incoming
+ protocol :tcp
+ dest_ports node[:exim][:daemon_smtp_ports]
+ source_ports "1024-65535"
end
else
- node[:exim][:daemon_smtp_ports].each do |port|
- firewall_rule "accept-inbound-smtp-#{port}" do
- action :accept
- source "bm:mail.openstreetmap.org"
- dest "fw"
- proto "tcp:syn"
- dest_ports port
- source_ports "1024:"
- end
+ smarthosts = []
+
+ search(:node, "exim_smarthost_name:*?").each do |host|
+ smarthosts |= host.ipaddresses(:role => :external)
+ end
+
+ firewall_rule "accept-inbound-smtp" do
+ action :accept
+ context :incoming
+ protocol :tcp
+ source smarthosts
+ dest_ports node[:exim][:daemon_smtp_ports]
+ source_ports "1024-65535"
+ not_if { smarthosts.empty? }
end
end
if node[:exim][:smarthost_via]
firewall_rule "deny-outbound-smtp" do
action :reject
- source "fw"
- dest "net"
- proto "tcp:syn"
+ context :outgoing
+ protocol :tcp
dest_ports "smtp"
end
end
<% end -%>
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
Alias /.well-known/mta-sts.txt <%= @directory %>/<%= domain %>.txt
<% end -%>
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
RedirectPermanent / https://<%= @name %>/
SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
</VirtualHost>
# DO NOT EDIT - This file is being maintained by Chef
+<% if node.platform?("ubuntu") && node[:lsb][:release].to_f >= 22.04 -%>
+# options for update-exim4.conf
+UPEX4OPTS=''
+# options for exim4
+EXIMSERVICE='-bdf -q30s'
+<% else -%>
# 'combined' - one daemon running queue and listening on SMTP port
# 'no' - no daemon running the queue
# 'separate' - two separate daemons
QFLAGS=''
# options for daemon listening on port 25
SMTPLISTENEROPTIONS=''
+<% end -%>
# only warn once about each error
-E4BCD_WATCH_PANICLOG='once'
+E4BCD_WATCH_PANICLOG='no'
# manual for details. The lists above are used in the access control lists for
# checking incoming messages. The names of these ACLs are defined here:
+acl_smtp_mail = acl_check_mail
acl_smtp_rcpt = acl_check_rcpt
acl_smtp_data = acl_check_data
queue_run_max = <%= node[:exim][:queue_run_max] %>
+# Maximum number of simultaneous SMTP connections
+
+smtp_accept_max = <%= node[:exim][:smtp_accept_max] %>
+
+
######################################################################
# ACL CONFIGURATION #
begin acl
+# This access control list is used for the MAIL command in an incoming
+# SMTP message.
+
+acl_check_mail:
+
+ accept
+
# This access control list is used for every RCPT command in an incoming
# SMTP message. The tests are run in order until the address is either
# accepted or denied.
message = Rejected because $sender_address is blacklisted\nQueries to postmaster@$qualify_domain
!hosts = +relay_from_hosts
+ deny sender_domains= partial-lsearch;/etc/exim4/blocked-sender-domains
+ message = Rejected because $sender_address is blacklisted\nQueries to postmaster@$qualify_domain
+ !hosts = +relay_from_hosts
+
# Accept mail to postmaster in any local domain, regardless of the source,
# and without verifying the sender.
# relay domains is to use a callout (add /callout), but please read the
# documentation about callouts before doing this.
- require verify = recipient
+ deny domains = +relay_to_domains
+ !verify = recipient/callout=use_sender
+
+ deny domains = !+relay_to_domains
+ !verify = recipient
<% if node[:exim][:dns_blacklists] -%>
# Deny any messages from hosts in certain blacklists.
<% else -%>
transport = <%= name %>
<% end -%>
+<% if details[:case_sensitive] -%>
+ caseful_local_part
+<% end -%>
<% end -%>
signed_smtp:
driver = smtp
+ connect_timeout = 1m
dkim_domain = ${lookup{${domain:$h_from:}}partial-lsearch{/etc/exim4/dkim-domains}{$value}}
dkim_selector = ${lookup{$dkim_domain}lsearch{/etc/exim4/dkim-selectors}{$value}}
dkim_private_key = /etc/exim4/dkim-keys/${dkim_domain}
to = $sender_address
subject = Re: $header_subject:
headers = MIME-Version: 1.0\nContent-Type: text/plain; charset=utf-8
- file = /etc/exim4/noreply/$local_part_data
+ file = ${lookup{$local_part}dsearch,filter=file,ret=full{/etc/exim4/noreply}}
user = Debian-exim
group = Debian-exim
# DO NOT EDIT - This file is being maintained by Chef
-[diskstats]
-env.exclude fd0
+set sendmail="smtp://localhost"
version "1.0.0"
supports "ubuntu"
-depends "munin"
+depends "prometheus"
# limitations under the License.
#
-include_recipe "munin"
+include_recipe "prometheus"
-package "fail2ban"
+package %w[
+ fail2ban
+ python3-systemd
+ ruby-webrick
+]
+
+if platform?("debian")
+ package "python3-inotify"
+else
+ package "gamin"
+end
template "/etc/fail2ban/jail.d/00-default.conf" do
source "jail.default.erb"
action [:enable, :start]
end
-munin_plugin "fail2ban"
+prometheus_exporter "fail2ban" do
+ port 9635
+ user "root"
+ restrict_address_families "AF_UNIX"
+end
property :jail, :kind_of => String, :name_property => true
property :filter, :kind_of => String
+property :backend, :kind_of => String
+property :journalmatch, :kind_of => String
property :logpath, :kind_of => String
property :protocol, :kind_of => String
property :ports, :kind_of => Array, :default => []
+property :bantime, :kind_of => [Integer, String]
+property :findtime, :kind_of => [Integer, String]
property :maxretry, :kind_of => Integer
property :ignoreips, :kind_of => Array
mode "644"
variables :name => new_resource.jail,
:filter => new_resource.filter,
+ :backend => new_resource.backend,
+ :journalmatch => new_resource.journalmatch,
:logpath => new_resource.logpath,
:protocol => new_resource.protocol,
:ports => new_resource.ports,
+ :bantime => new_resource.bantime,
+ :findtime => new_resource.findtime,
:maxretry => new_resource.maxretry,
:ignoreips => new_resource.ignoreips
end
[DEFAULT]
destemail = admins@openstreetmap.org
-banaction = shorewall
+banaction = nftables[type=multiport]
+banaction_allports = nftables[type=allports]
bantime = 14400
<% if @filter -%>
filter = <%= @filter %>
<% end -%>
+<% if @backend -%>
+backend = <%= @backend %>
+<% end -%>
+<% if @journalmatch -%>
+journalmatch = <%= @journalmatch %>
+<% end -%>
<% if @logpath -%>
logpath = <%= @logpath %>
<% end -%>
+<% if @bantime -%>
+bantime = <%= @bantime %>
+<% end -%>
+<% if @findtime -%>
+findtime = <%= @findtime %>
+<% end -%>
<% if @maxretry -%>
maxretry = <%= @maxretry %>
<% end -%>
+++ /dev/null
-# Forum Cookbook
-
-This cookbook installs and configures the fluxbb forums software used at
-https://forum.openstreetmap.org
+++ /dev/null
-# Enable the "forum" role
-default[:accounts][:users][:forum][:status] = :role
+++ /dev/null
-#
-# Cookbook:: forum
-# Recipe:: default
-#
-# Copyright:: 2014, OpenStreetMap Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-include_recipe "accounts"
-include_recipe "apache"
-include_recipe "git"
-include_recipe "mysql"
-include_recipe "php::fpm"
-
-cache_dir = Chef::Config[:file_cache_path]
-
-passwords = data_bag_item("forum", "passwords")
-
-package %w[
- php-cli
- php-mysql
- php-xml
- php-apcu
- unzip
-]
-
-apache_module "env"
-apache_module "rewrite"
-
-ssl_certificate "forum.openstreetmap.org" do
- domains ["forum.openstreetmap.org", "forum.osm.org"]
- notifies :reload, "service[apache2]"
-end
-
-php_fpm "forum.openstreetmap.org" do
- php_admin_values "open_basedir" => "/srv/forum.openstreetmap.org/html/:/usr/share/php/:/tmp/",
- "disable_functions" => "exec,shell_exec,system,passthru,popen,proc_open"
- prometheus_port 9253
-end
-
-apache_site "forum.openstreetmap.org" do
- template "apache.erb"
-end
-
-directory "/srv/forum.openstreetmap.org" do
- owner "forum"
- group "forum"
- mode "755"
-end
-
-git "/srv/forum.openstreetmap.org/html/" do
- action :sync
- repository "http://github.com/openstreetmap/openstreetmap-forum.git"
- revision "openstreetmap-1.5.10"
- depth 1
- user "forum"
- group "forum"
- notifies :reload, "service[apache2]"
-end
-
-remote_file "#{cache_dir}/air3_v0.8.zip" do
- action :create_if_missing
- source "https://fluxbb.org/resources/styles/air3/releases/0.8/air3_v0.8.zip"
- owner "root"
- group "root"
- mode "644"
- backup false
-end
-
-execute "#{cache_dir}/air3_v0.8.zip" do
- action :nothing
- command "unzip -o -qq #{cache_dir}/air3_v0.8.zip Air3.css 'Air3/*'"
- cwd "/srv/forum.openstreetmap.org/html/style"
- user "forum"
- group "forum"
- subscribes :run, "remote_file[#{cache_dir}/air3_v0.8.zip]", :immediately
-end
-
-directory "/srv/forum.openstreetmap.org/html/cache/" do
- owner "www-data"
- group "www-data"
- mode "755"
-end
-
-directory "/srv/forum.openstreetmap.org/html/img/avatars/" do
- owner "www-data"
- group "www-data"
- mode "755"
-end
-
-template "/srv/forum.openstreetmap.org/html/config.php" do
- source "config.php.erb"
- owner "forum"
- group "www-data"
- mode "440"
- variables :passwords => passwords
-end
-
-mysql_user "forum@localhost" do
- password passwords["database"]
-end
-
-mysql_database "forum" do
- permissions "forum@localhost" => :all
-end
-
-template "/etc/cron.daily/forum-backup" do
- source "backup.cron.erb"
- owner "root"
- group "root"
- mode "750"
- variables :passwords => passwords
-end
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-<VirtualHost *:80>
- ServerName forum.openstreetmap.org
- ServerAlias forum.osm.org
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/forum.openstreetmap.org-access.log combined
- ErrorLog /var/log/apache2/forum.openstreetmap.org-error.log
-
- RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
- RedirectPermanent / https://forum.openstreetmap.org/
-</VirtualHost>
-
-<VirtualHost *:443>
- ServerAlias forum.osm.org
- ServerAdmin webmaster@openstreetmap.org
-
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/forum.openstreetmap.org.pem
- SSLCertificateKeyFile /etc/ssl/private/forum.openstreetmap.org.key
-
- CustomLog /var/log/apache2/forum.openstreetmap.org-access.log combined
- ErrorLog /var/log/apache2/forum.openstreetmap.org-error.log
-
- RedirectPermanent / https://forum.openstreetmap.org/
-</VirtualHost>
-
-<VirtualHost *:443>
- ServerName forum.openstreetmap.org
- ServerAdmin webmaster@openstreetmap.org
-
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/forum.openstreetmap.org.pem
- SSLCertificateKeyFile /etc/ssl/private/forum.openstreetmap.org.key
-
- CustomLog /var/log/apache2/forum.openstreetmap.org-access.log combined
- ErrorLog /var/log/apache2/forum.openstreetmap.org-error.log
-
- DocumentRoot /srv/forum.openstreetmap.org/html
-
- <FilesMatch ".+\.ph(ar|p|tml)$">
- SetHandler "proxy:unix:/run/php/forum.openstreetmap.org.sock|fcgi://127.0.0.1"
- </FilesMatch>
-</VirtualHost>
-
-<Directory /srv/forum.openstreetmap.org/html>
- RewriteEngine on
- RewriteRule ^config\.php$ - [F,L]
-
- Options -Indexes
-
- Require all granted
-</Directory>
-
-<Directory /srv/forum.openstreetmap.org/html/img>
- <FilesMatch ".+\.ph(ar|p|tml)$">
- SetHandler None
- </FilesMatch>
-</Directory>
+++ /dev/null
-#!/bin/sh
-
-# DO NOT EDIT - This file is being maintained by Chef
-
-T=$(mktemp -d -t -p /var/tmp forum.XXXXXXXXXX)
-D=$(date +%Y-%m-%d)
-B=forum-$D.tar.gz
-
-mkdir $T/forum-$D
-echo '[mysqldump]' > $T/mysqldump.opts
-echo 'user=forum' >> $T/mysqldump.opts
-echo 'password=<%= @passwords["database"] %>' >> $T/mysqldump.opts
-mysqldump --defaults-file=$T/mysqldump.opts --opt --no-tablespaces forum > $T/forum-$D/forum.sql
-ln -s /srv/forum.openstreetmap.org $T/forum-$D/www
-
-export RSYNC_RSH="ssh -ax"
-
-nice tar --create --dereference --directory=$T forum-$D | nice gzip --rsyncable -9 > $T/$B
-nice rsync --preallocate --fuzzy $T/$B backup::backup
-
-rm -rf $T
+++ /dev/null
-<?php
-
-$db_type = 'mysqli';
-$db_host = 'localhost';
-$db_name = 'forum';
-$db_username = 'forum';
-$db_password = '<%= @passwords["database"] %>';
-$db_prefix = 'osm_';
-$p_connect = false;
-
-$cookie_name = 'forum_cookie';
-$cookie_domain = '';
-$cookie_path = '/';
-$cookie_secure = 1;
-$cookie_seed = '<%= @passwords["cookie_seed"] %>';
-
-define('PUN', 1);
version "1.0.0"
supports "ubuntu"
depends "apache"
-depends "git"
depends "mediawiki"
+depends "podman"
mediawiki_site "board.osmfoundation.org" do
sitename "OSMF Board Wiki"
metanamespace "OSMFBoard"
- directory "/srv/board.osmfoundation.org"
fpm_prometheus_port 11004
database_name "board-wiki"
database_user "board-wikiuser"
admin_password passwords["board"]["admin"]
logo "/Wiki.png"
email_contact "webmaster@openstreetmap.org"
- email_sender "webmaster@openstreetmap.org"
+ email_sender "wiki@noreply.openstreetmap.org"
email_sender_name "OSMF Board Wiki"
private_site true
- recaptcha_public_key "6LflIQATAAAAAMXyDWpba-FgipVzE-aGF4HIR59N"
- recaptcha_private_key passwords["board"]["recaptcha"]
- version "1.34"
+ version "1.39"
end
cookbook_file "/srv/board.osmfoundation.org/Wiki.png" do
mediawiki_site "dwg.osmfoundation.org" do
sitename "OSMF Data Working Group Wiki"
metanamespace "OSMFDWG"
- directory "/srv/dwg.osmfoundation.org"
fpm_prometheus_port 11002
database_name "dwg-wiki"
database_user "dwg-wikiuser"
admin_password passwords["dwg"]["admin"]
logo "/Wiki.png"
email_contact "webmaster@openstreetmap.org"
- email_sender "webmaster@openstreetmap.org"
+ email_sender "wiki@noreply.openstreetmap.org"
email_sender_name "OSMF Board Wiki"
private_site true
- recaptcha_public_key "6LflIQATAAAAAMXyDWpba-FgipVzE-aGF4HIR59N"
- recaptcha_private_key passwords["dwg"]["recaptcha"]
- version "1.34"
+ extra_file_extensions %w[pptx]
+ version "1.39"
end
cookbook_file "/srv/dwg.osmfoundation.org/Wiki.png" do
--- /dev/null
+#
+# Cookbook:: foundation
+# Recipe:: mastodon
+#
+# Copyright:: 2023, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "podman::apache"
+
+podman_site "en.openstreetmap.town" do
+ image "ghcr.io/openstreetmap/en.openstreetmap.town-website:latest"
+end
mediawiki_site "mwg.osmfoundation.org" do
sitename "OSMF Membership Working Group Wiki"
metanamespace "OSMFMWG"
- directory "/srv/mwg.osmfoundation.org"
fpm_prometheus_port 11003
database_name "mwg_wiki"
database_user "mwg_wikiuser"
admin_password passwords["mwg"]["admin"]
logo "/Wiki.png"
email_contact "webmaster@openstreetmap.org"
- email_sender "webmaster@openstreetmap.org"
+ email_sender "wiki@noreply.openstreetmap.org"
email_sender_name "OSMF Board Wiki"
private_site true
- recaptcha_public_key "6LflIQATAAAAAMXyDWpba-FgipVzE-aGF4HIR59N"
- recaptcha_private_key passwords["mwg"]["recaptcha"]
- version "1.34"
+ version "1.39"
end
cookbook_file "/srv/mwg.osmfoundation.org/Wiki.png" do
# limitations under the License.
#
-include_recipe "apache"
-include_recipe "git"
+include_recipe "podman::apache"
-package %w[
- gcc
- g++
- make
- ruby
- ruby-dev
- libssl-dev
- zlib1g-dev
- pkg-config
-]
-
-gem_package "bundler" do
- version "1.17.3"
-end
-
-git "/srv/operations.osmfoundation.org" do
- action :sync
- repository "https://github.com/openstreetmap/owg-website.git"
- depth 1
- user "root"
- group "root"
- notifies :run, "execute[/srv/operations.osmfoundation.org/Gemfile]"
-end
-
-directory "/srv/operations.osmfoundation.org/_site" do
- mode "755"
- owner "nobody"
- group "nogroup"
-end
-
-# Workaround https://github.com/jekyll/jekyll/issues/7804
-# by creating a .jekyll-cache folder
-directory "/srv/operations.osmfoundation.org/.jekyll-cache" do
- mode "755"
- owner "nobody"
- group "nogroup"
-end
-
-execute "/srv/operations.osmfoundation.org/Gemfile" do
- action :nothing
- command "bundle install --deployment"
- cwd "/srv/operations.osmfoundation.org"
- user "root"
- group "root"
- notifies :run, "execute[/srv/operations.osmfoundation.org]"
-end
-
-execute "/srv/operations.osmfoundation.org" do
- command "bundle exec jekyll build --trace"
- cwd "/srv/operations.osmfoundation.org"
- user "nobody"
- group "nogroup"
-end
-
-ssl_certificate "operations.osmfoundation.org" do
- domains "operations.osmfoundation.org"
- notifies :reload, "service[apache2]"
-end
-
-apache_site "operations.osmfoundation.org" do
- template "apache.owg.erb"
- directory "/srv/operations.osmfoundation.org/_site"
+podman_site "operations.osmfoundation.org" do
+ image "ghcr.io/openstreetmap/owg-website:latest"
+ aliases ["operations.openstreetmap.org", "operations.osm.org"]
end
--- /dev/null
+#
+# Cookbook:: foundation
+# Recipe:: welcome
+#
+# Copyright:: 2023, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "podman::apache"
+
+podman_site "welcome.openstreetmap.org" do
+ image "ghcr.io/osmfoundation/welcome-mat:latest"
+ aliases ["welcome.osm.org"]
+end
passwords = data_bag_item("foundation", "passwords")
-mediawiki_site "wiki.osmfoundation.org" do
- aliases ["www.osmfoundation.org", "osmfoundation.org",
+mediawiki_site "osmfoundation.org" do
+ aliases ["wiki.osmfoundation.org", "www.osmfoundation.org",
"foundation.openstreetmap.org", "foundation.osm.org"]
sitename "OpenStreetMap Foundation"
- directory "/srv/wiki.osmfoundation.org"
fpm_max_children 20
fpm_start_servers 5
fpm_min_spare_servers 5
database_password passwords["wiki"]["database"]
admin_password passwords["wiki"]["admin"]
skin "OSMFoundation"
- logo "/Wiki.png"
+ logo "/w/skins/OSMFoundation/img/logo.png"
email_contact "webmaster@openstreetmap.org"
- email_sender "webmaster@openstreetmap.org"
+ email_sender "wiki@noreply.openstreetmap.org"
email_sender_name "OSMF Wiki"
private_accounts true
- recaptcha_public_key "6LflIQATAAAAAMXyDWpba-FgipVzE-aGF4HIR59N"
- recaptcha_private_key passwords["wiki"]["recaptcha"]
- extra_file_extensions ["mp3"]
- version "1.34"
-end
-
-mediawiki_skin "osmf" do
- site "wiki.osmfoundation.org"
- repository "https://github.com/openstreetmap/mediawiki-skins-osmf.git"
- revision "master"
+ extra_file_extensions %w[mp3 pptx]
+ version "1.39"
end
mediawiki_skin "OSMFoundation" do
- site "wiki.osmfoundation.org"
+ site "osmfoundation.org"
repository "https://github.com/osmfoundation/osmf-mediawiki-skin.git"
revision "master"
legacy false
end
-cookbook_file "/srv/wiki.osmfoundation.org/Wiki.png" do
+cookbook_file "/srv/osmfoundation.org/Wiki.png" do
+ owner node[:mediawiki][:user]
+ group node[:mediawiki][:group]
+ mode "644"
+end
+
+template "/srv/osmfoundation.org/robots.txt" do
owner node[:mediawiki][:user]
group node[:mediawiki][:group]
mode "644"
+ source "robots.txt.erb"
end
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-<VirtualHost *:443>
- ServerName <%= @name %>
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
- ErrorLog /var/log/apache2/<%= @name %>-error.log
-
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
- SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
-
- DocumentRoot <%= @directory %>
-</VirtualHost>
-
-<VirtualHost *:80>
- ServerName <%= @name %>
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
- ErrorLog /var/log/apache2/<%= @name %>-error.log
-
- RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
- RedirectPermanent / https://<%= @name %>/
-</VirtualHost>
-
-<Directory <%= @directory %>>
- Require all granted
-</Directory>
--- /dev/null
+User-agent: ia_archiver
+Allow: /
+
+User-agent: 008
+Disallow: /
+
+User-agent: *
+Disallow: /index.php/
+Disallow: /wiki/Spam
+Disallow: /wiki/Donate/International_Bank_Transfers
+Allow: /w/load.php
+Allow: /w/images/
+Allow: /w/skins/
+Disallow: /w/
+Disallow: /wiki/Special:Collection
+Disallow: /wiki/Special:Random
+Disallow: /wiki/Special%3ARandom
+Disallow: /wiki/Special:Search
+
+User-agent: Exabot
+Crawl-delay: 60
firewall_rule "accept-ftp-tcp" do
action :accept
- source "net"
- dest "fw"
- proto "tcp"
+ context :incoming
+ protocol :tcp
dest_ports "ftp"
- source_ports "-"
helper "ftp"
end
include_recipe "geoipupdate"
+servers = search(:node, "roles:geodns").collect(&:name).sort
+
+servers << "dummy.example.com" if servers.empty?
+
package %w[
gdnsd
]
mode "755"
end
-%w[tile nominatim].each do |zone|
+%w[nominatim].each do |zone|
%w[map resource weighted].each do |type|
template "/etc/gdnsd/config.d/#{zone}.#{type}" do
action :create_if_missing
owner "root"
group "root"
mode "644"
+ variables :servers => servers
notifies :restart, "service[gdnsd]"
end
user "root"
exec_start "/bin/systemctl reload-or-restart gdnsd"
standard_output "null"
- private_tmp true
- private_devices true
- protect_system "full"
- protect_home true
- no_new_privileges true
+ sandbox true
+ restrict_address_families "AF_UNIX"
end
systemd_path "gdnsd-reload" do
firewall_rule "accept-dns-udp" do
action :accept
- source "net"
- dest "fw"
- proto "udp"
+ context :incoming
+ protocol :udp
dest_ports "domain"
end
firewall_rule "accept-dns-tcp" do
action :accept
- source "net"
- dest "fw"
- proto "tcp:syn"
+ context :incoming
+ protocol :tcp
dest_ports "domain"
end
plugins => {
geoip => {
maps => {
- $include{config.d/tile.map}
$include{config.d/nominatim.map}
}
resources => {
- $include{config.d/tile.resource}
$include{config.d/nominatim.resource}
}
},
weighted => {
- $include{config.d/tile.weighted}
$include{config.d/nominatim.weighted}
}
}
$TTL 86400
-@ SOA saphira.openstreetmap.org. hostmaster.openstreetmap.org. (
+@ SOA <%= @servers.first %>. hostmaster.openstreetmap.org. (
3 ; serial
86400 ; refresh
7200 ; retry
3600 ; ncache
)
-@ 86400 NS balerion.openstreetmap.org.
-@ 86400 NS chrysophylax.openstreetmap.org.
-@ 86400 NS katie.openstreetmap.org.
-@ 86400 NS saphira.openstreetmap.org.
-@ 86400 NS stormfly-04.openstreetmap.org.
-@ 86400 NS ridgeback.openstreetmap.org.
+<% @servers.each do |server| -%>
+@ 86400 NS <%= server %>.
+<% end -%>
-tile 300 DYNC geoip!tile
nominatim 300 DYNC geoip!nominatim
default[:geoipupdate][:account] = "149244"
default[:geoipupdate][:editions] = %w[GeoLite2-ASN GeoLite2-City GeoLite2-Country]
-
-default[:apt][:sources] |= ["maxmind"]
+default[:geoipupdate][:directory] = if platform?("debian")
+ "/var/lib/GeoIP"
+ else
+ "/usr/share/GeoIP"
+ end
# limitations under the License.
#
-include_recipe "apt"
+include_recipe "apt::maxmind"
license_keys = data_bag_item("geoipupdate", "license-keys")
command "geoipupdate"
user "root"
group "root"
- not_if { ENV.key?("TEST_KITCHEN") || node[:geoipupdate][:editions].all? { |edition| ::File.exist?("/usr/share/GeoIP/#{edition}.mmdb") } }
+ not_if { kitchen? || node[:geoipupdate][:editions].all? { |edition| ::File.exist?("#{node[:geoipupdate][:directory]}/#{edition}.mmdb") } }
end
systemd_service "geoipupdate" do
description "Update GeoIP databases"
user "root"
exec_start "/usr/bin/geoipupdate"
- private_tmp true
- private_devices true
- protect_system "strict"
- protect_home true
- read_write_paths "/usr/share/GeoIP"
+ sandbox :enable_network => true
+ read_write_paths node[:geoipupdate][:directory]
end
systemd_timer "geoipupdate" do
AccountID <%= node[:geoipupdate][:account] %>
LicenseKey <%= @license_keys[node[:geoipupdate][:account]] %>
EditionIDs <%= Array(node[:geoipupdate][:editions]).join(" ") %>
+DatabaseDirectory <%= node[:geoipupdate][:directory] %>
default[:git][:private_user] = "git"
default[:git][:private_group] = "git"
default[:git][:private_nodes] = "fqdn:*"
-
-default[:apt][:sources] |= ["git-core"]
supports "ubuntu"
depends "accounts"
depends "apache"
-depends "apt"
depends "networking"
# limitations under the License.
#
-include_recipe "apt"
-
package "git"
mode "2775"
end
+template "/etc/gitconfig" do
+ source "gitconfig.erb"
+ owner "root"
+ group "root"
+ mode "644"
+end
+
Dir.glob("#{git_directory}/*/*.git").each do |repository|
template "#{repository}/hooks/post-update" do
source "post-update.erb"
package "gitweb"
+apache_module "cgid"
apache_module "rewrite"
git_site = node[:git][:host]
mode "644"
end
+template "/srv/#{git_site}/indextext.html" do
+ source "indextext.html.erb"
+ owner "root"
+ group "root"
+ mode "644"
+end
+
ssl_certificate git_site do
domains [git_site] + Array(node[:git][:aliases])
notifies :reload, "service[apache2]"
<% end -%>
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
RedirectPermanent / https://<%= @name %>/
SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
SetEnv GIT_PROJECT_ROOT /var/lib/git
# KeepaliveTimeout longer than git config uploadpack.keepalive 5 second default
KeepAliveTimeout 20
+ RewriteEngine on
+ RewriteRule ^/cgimap\.git.* https://github.com/zerebubuth/openstreetmap-cgimap [QSD,L,R=permanent]
+ RewriteRule ^/planetdump\.git.* https://github.com/openstreetmap/planetdump [QSD,L,R=permanent]
+ RewriteRule ^/gpx-import\.git.* https://github.com/openstreetmap/gpx-import [QSD,L,R=permanent]
+ RewriteRule ^/potlatch2\.git.* https://github.com/openstreetmap/potlatch2 [QSD,L,R=permanent]
+
ScriptAlias /public /usr/lib/git-core/git-http-backend/public
ScriptAlias /private /usr/lib/git-core/git-http-backend/private
Alias /gitweb /usr/share/gitweb
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+[safe]
+ directory = /var/lib/chef/public
+ directory = /var/lib/chef/private
+ directory = /var/lib/dns
#$home_link = $my_uri || "/";
# html text to include at home page
-$home_text = "indextext.html";
+$home_text = "/srv/<%= node[:git][:host] %>/indextext.html";
# file with project list; by default, simply scan the projectroot dir.
$projects_list = $projectroot;
--- /dev/null
+<h2>Want to contribute to OpenStreetMap software?</h2>
+<p>Head over to <a href="https://github.com/openstreetmap/">github.com/openstreetmap/</a></p>
+<p>git.openstreetmap.org is an internal system we use as part of our deployment system.</p>
git "/srv/gps-tile.openstreetmap.org/import" do
action :sync
- repository "https://github.com/ericfischer/gpx-import.git"
+ repository "https://github.com/e-n-f/gpx-import.git"
revision "live"
depth 1
user "gpstile"
git "/srv/gps-tile.openstreetmap.org/datamaps" do
action :sync
- repository "https://github.com/ericfischer/datamaps.git"
+ repository "https://github.com/e-n-f/datamaps.git"
revision "live"
depth 1
user "gpstile"
git "/srv/gps-tile.openstreetmap.org/updater" do
action :sync
- repository "https://github.com/ericfischer/gpx-updater.git"
+ repository "https://github.com/openstreetmap/gpx-updater.git"
revision "live"
depth 1
user "gpstile"
group "gpstile"
end
+directory "/srv/gps-tile.openstreetmap.org/tracks" do
+ owner "gpstile"
+ group "gpstile"
+ mode "755"
+end
+
+directory "/srv/gps-tile.openstreetmap.org/shapes" do
+ owner "gpstile"
+ group "gpstile"
+ mode "755"
+end
+
systemd_service "gps-update" do
description "GPS tile update daemon"
after ["network.target", "memcached.service"]
user "gpstile"
working_directory "/srv/gps-tile.openstreetmap.org"
exec_start "/srv/gps-tile.openstreetmap.org/updater/update"
- private_tmp true
- private_devices true
- protect_system "full"
- protect_home true
- no_new_privileges true
+ nice 10
+ sandbox :enable_network => true
+ read_write_paths "/srv/gps-tile.openstreetmap.org"
restart "on-failure"
end
files_mode "644"
end
+apache_module "cgid"
apache_module "headers"
apache_module "rewrite"
RedirectPermanent /gps-lines/tile /lines
# Setup logging
- CustomLog /var/log/apache2/access.log combined
+ CustomLog /var/log/apache2/access.log combined_extended
ErrorLog /var/log/apache2/error.log
BufferedLogs on
RewriteRule (.*) https://%{SERVER_NAME}/$1 [R=permanent,L]
# Setup logging
- CustomLog /var/log/apache2/access.log combined
+ CustomLog /var/log/apache2/access.log combined_extended
ErrorLog /var/log/apache2/error.log
BufferedLogs on
</VirtualHost>
default[:hardware][:modules] = %w[lp]
+default[:hardware][:blacklisted_modules] = %w[]
default[:hardware][:grub][:cmdline] = %w[nomodeset]
default[:hardware][:sensors] = {}
default[:hardware][:hwmon] = {}
default[:hardware][:ipmi][:excluded_sensors] = []
+default[:hardware][:ipmi][:custom_args] = []
if node[:dmi] && node[:dmi][:system]
case node[:dmi][:system][:manufacturer]
when "HP"
- default[:apt][:sources] |= ["management-component-pack"]
-
case node[:dmi][:system][:product_name]
when "ProLiant DL360 G6", "ProLiant DL360 G7", "ProLiant SE326M1R2"
default[:hardware][:sensors][:"power_meter-*"][:power][:power1] = { :ignore => true }
end
+
+ case node[:dmi][:system][:product_name]
+ when "ProLiant DL360 G6", "ProLiant DL360 G7", "ProLiant SE326M1R2", "ProLiant DL360e Gen8", "ProLiant DL360p Gen8"
+ default[:hardware][:ipmi][:custom_args] |= ["--workaround-flags=discretereading"]
+ end
end
end
end
end
-if node[:kernel] && node[:kernel][:modules]
- raidmods = node[:kernel][:modules].keys & %w[cciss hpsa mptsas mpt2sas mpt3sas megaraid_mm megaraid_sas aacraid]
-
- default[:apt][:sources] |= ["hwraid"] unless raidmods.empty?
-end
-
if node[:kernel][:modules].include?("ipmi_si")
default[:hardware][:modules] |= ["ipmi_devintf"]
-end
-if File.exist?("/proc/xen")
- default[:hardware][:watchdog] = "xen_wdt"
-elsif node[:kernel][:modules].include?("i6300esb")
- default[:hardware][:watchdog] = "none"
+ if node[:kernel][:modules].include?("acpi_power_meter")
+ default[:hardware][:modules] |= ["acpi_ipmi"]
+ end
end
if File.exist?("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor") &&
default[:sysfs][:cpufreq_ondemand][:comment] = "Tune the ondemand CPU frequency governor"
default[:sysfs][:cpufreq_ondemand][:parameters][:"devices/system/cpu/cpufreq/ondemand/up_threshold"] = "25"
default[:sysfs][:cpufreq_ondemand][:parameters][:"devices/system/cpu/cpufreq/ondemand/sampling_down_factor"] = "100"
+ default[:sysfs][:cpufreq_ondemand][:parameters][:"devices/system/cpu/cpufreq/ondemand/ignore_nice_load"] = "1"
+end
+
+energy_perf_bias = Dir.glob("/sys/devices/system/cpu/cpu*/power/energy_perf_bias")
+
+unless energy_perf_bias.empty?
+ default[:sysfs][:cpu_power_energy_perf_bias][:comment] = "Set CPU Energy-Performance Bias Preference to balance-performance"
+
+ energy_perf_bias.sort.each do |path|
+ default[:sysfs][:cpu_power_energy_perf_bias][:parameters][path.sub(%r{^/sys/}, "")] = "4"
+ end
end
depends "apt"
depends "chef"
depends "git"
-depends "munin"
depends "prometheus"
depends "ohai"
depends "tools"
include_recipe "apt"
include_recipe "git"
-include_recipe "munin"
include_recipe "prometheus"
include_recipe "sysfs"
include_recipe "tools"
template "ohai.rb.erb"
end
-case node[:cpu][:"0"][:vendor_id]
-when "GenuineIntel"
- package "intel-microcode"
-when "AuthenticAMD"
- package "amd64-microcode"
+if platform?("debian")
+ package "firmware-linux"
+end
+
+if node[:cpu] && node[:cpu][:"0"] && node[:cpu][:"0"][:vendor_id]
+ case node[:cpu][:"0"][:vendor_id]
+ when "GenuineIntel"
+ package "intel-microcode"
+ when "AuthenticAMD"
+ package "amd64-microcode"
+ end
end
if node[:dmi] && node[:dmi][:system]
end
case manufacturer
-when "HP"
+when "HP", "HPE"
+ include_recipe "apt::management-component-pack"
+
package "hponcfg"
+ execute "update-ilo" do
+ action :nothing
+ command "/usr/sbin/hponcfg -f /etc/ilo-defaults.xml"
+ not_if { kitchen? }
+ end
+
+ template "/etc/ilo-defaults.xml" do
+ source "ilo-defaults.xml.erb"
+ owner "root"
+ group "root"
+ mode "644"
+ notifies :run, "execute[update-ilo]"
+ end
+
package "hp-health" do
action :install
notifies :restart, "service[hp-health]"
+ only_if { platform?("ubuntu") && node[:lsb][:release].to_f < 22.04 }
end
service "hp-health" do
action [:enable, :start]
supports :status => true, :restart => true
+ only_if { platform?("ubuntu") && node[:lsb][:release].to_f < 22.04 }
end
if product.end_with?("Gen8", "Gen9")
action [:enable, :start]
supports :status => true, :restart => true
end
+ elsif product.end_with?("Gen10")
+ package "amsd" do
+ action :install
+ notifies :restart, "service[amsd]"
+ end
+
+ service "amsd" do
+ action [:enable, :start]
+ supports :status => true, :restart => true
+ end
end
- units << "1"
+ units << if product.end_with?("Gen10")
+ "0"
+ else
+ "1"
+ end
when "TYAN"
units << "0"
when "TYAN Computer Corporation"
units.sort.uniq.each do |unit|
service "serial-getty@ttyS#{unit}" do
action [:enable, :start]
+ not_if { kitchen? }
end
end
execute "update-grub" do
action :nothing
command "/usr/sbin/update-grub"
- not_if { ENV["TEST_KITCHEN"] }
+ not_if { kitchen? }
end
template "/etc/default/grub" do
end
end
+package "initramfs-tools"
+
execute "update-initramfs" do
action :nothing
command "update-initramfs -u -k all"
notifies :run, "execute[update-initramfs]"
end
-package "haveged"
-service "haveged" do
- action [:enable, :start]
+# haveged is only required on older kernels
+# /dev/random is not blocking anymore in 5.15+
+if Chef::Util.compare_versions(node[:kernel][:release], [5, 15]).negative?
+ package "haveged"
+ service "haveged" do
+ action [:enable, :start]
+ end
+else
+ service "haveged" do
+ action [:stop, :disable]
+ end
+ package "haveged" do
+ action :remove
+ end
+end
+
+watchdog_module = %w[hpwdt sp5100_tco].find do |module_name|
+ node[:hardware][:pci]&.any? { |_, pci| pci[:modules]&.any?(module_name) }
end
if node[:kernel][:modules].include?("ipmi_si")
prometheus_exporter "ipmi" do
port 9290
+ user "root"
+ private_devices false
+ protect_clock false
+ system_call_filter ["@system-service", "@raw-io"]
options "--config.file=/etc/prometheus/ipmi_local.yml"
subscribes :restart, "template[/etc/prometheus/ipmi_local.yml]"
end
+
+ watchdog_module ||= "ipmi_watchdog"
end
package "irqbalance"
supports :status => false, :restart => true, :reload => false
end
-# Link Layer Discovery Protocol Daemon
package "lldpd"
+
service "lldpd" do
action [:start, :enable]
supports :status => true, :restart => true, :reload => true
end
+ohai_plugin "lldp" do
+ template "lldp.rb.erb"
+end
+
+package %w[
+ rasdaemon
+ ruby-sqlite3
+]
+
+service "rasdaemon" do
+ action [:enable, :start]
+end
+
+prometheus_exporter "rasdaemon" do
+ port 9797
+ user "root"
+end
+
tools_packages = []
status_packages = {}
when "mpt2sas", "mpt3sas"
tools_packages << "sas2ircu"
status_packages["sas2ircu-status"] ||= []
- when "megaraid_mm"
- tools_packages << "megactl"
- status_packages["megaraid-status"] ||= []
when "megaraid_sas"
tools_packages << "megacli"
status_packages["megaclisas-status"] ||= []
depth 1
user "root"
group "root"
- not_if { ENV["TEST_KITCHEN"] }
+ not_if { kitchen? }
end
else
directory "/opt/areca" do
end
end
-if status_packages.include?("cciss-vol-status")
- template "/usr/local/bin/cciss-vol-statusd" do
- source "cciss-vol-statusd.erb"
- owner "root"
- group "root"
- mode "755"
- notifies :restart, "service[cciss-vol-statusd]"
- end
+include_recipe "apt::hwraid" unless status_packages.empty?
- systemd_service "cciss-vol-statusd" do
- description "Check cciss_vol_status values in the background"
- exec_start "/usr/local/bin/cciss-vol-statusd"
- private_tmp true
- protect_system "full"
- protect_home true
- no_new_privileges true
- notifies :restart, "service[cciss-vol-statusd]"
- end
-else
- systemd_service "cciss-vol-statusd" do
- action :delete
- end
-
- template "/usr/local/bin/cciss-vol-statusd" do
- action :delete
- end
-end
-
-%w[cciss-vol-status mpt-status sas2ircu-status megaraid-status megaclisas-status aacraid-status].each do |status_package|
+%w[cciss-vol-status mpt-status sas2ircu-status megaclisas-status aacraid-status].each do |status_package|
if status_packages.include?(status_package)
package status_package
- template "/etc/default/#{status_package}d" do
- source "raid.default.erb"
- owner "root"
- group "root"
- mode "644"
- variables :devices => status_packages[status_package]
+ service "#{status_package}d" do
+ action [:stop, :disable]
end
- service "#{status_package}d" do
- action [:start, :enable]
- supports :status => false, :restart => true, :reload => false
- subscribes :restart, "template[/etc/default/#{status_package}d]"
+ file "/etc/default/#{status_package}d" do
+ action :delete
end
else
package status_package do
action :purge
end
-
- file "/etc/default/#{status_package}d" do
- action :delete
- end
end
end
+systemd_service "cciss-vol-statusd" do
+ action :delete
+end
+
+template "/usr/local/bin/cciss-vol-statusd" do
+ action :delete
+end
+
disks = if node[:hardware][:disk]
node[:hardware][:disk][:disks]
else
[]
end
+unless nvmes.empty?
+ package "nvme-cli"
+end
+
intel_nvmes = nvmes.select { |pci| pci[:vendor_name] == "Intel Corporation" }
if !intel_ssds.empty? || !intel_nvmes.empty?
package "unzip"
- intel_mas_tool_version = "1.8"
- intel_mas_package_version = "#{intel_mas_tool_version}.140-0"
+ sst_tool_version = "1.3"
+ sst_package_version = "#{sst_tool_version}.208-0"
- remote_file "#{Chef::Config[:file_cache_path]}/Intel_MAS_CLI_Tool_#{intel_mas_tool_version}_Linux.zip" do
- source "https://downloadmirror.intel.com/30509/eng/Intel%C2%AE_MAS_CLI_Tool_Linux_#{intel_mas_tool_version}.zip"
- end
+ # remote_file "#{Chef::Config[:file_cache_path]}/SST_CLI_Linux_#{sst_tool_version}.zip" do
+ # source "https://downloadmirror.intel.com/743764/SST_CLI_Linux_#{sst_tool_version}.zip"
+ # end
- execute "#{Chef::Config[:file_cache_path]}/Intel_MAS_CLI_Tool_#{intel_mas_tool_version}_Linux.zip" do
- command "unzip Intel_MAS_CLI_Tool_#{intel_mas_tool_version}_Linux.zip intelmas_#{intel_mas_package_version}_amd64.deb"
+ execute "#{Chef::Config[:file_cache_path]}/SST_CLI_Linux_#{sst_tool_version}.zip" do
+ command "unzip SST_CLI_Linux_#{sst_tool_version}.zip sst_#{sst_package_version}_amd64.deb"
cwd Chef::Config[:file_cache_path]
user "root"
group "root"
- not_if { ::File.exist?("#{Chef::Config[:file_cache_path]}/intelmas_#{intel_mas_package_version}_amd64.deb") }
+ not_if { ::File.exist?("#{Chef::Config[:file_cache_path]}/sst_#{sst_package_version}_amd64.deb") }
end
- dpkg_package "intelmas" do
- version "#{intel_mas_package_version}"
- source "#{Chef::Config[:file_cache_path]}/intelmas_#{intel_mas_package_version}_amd64.deb"
+ dpkg_package "sst" do
+ version "#{sst_package_version}"
+ source "#{Chef::Config[:file_cache_path]}/sst_#{sst_package_version}_amd64.deb"
end
- dpkg_package "isdct" do
+ dpkg_package "intelmas" do
action :purge
end
end
if controller && controller[:device]
device = controller[:device].sub("/dev/", "")
smart = disk[:smart_device]
-
- if device.start_with?("cciss/") && smart =~ /^cciss,(\d+)$/
- array = node[:hardware][:disk][:arrays][disk[:arrays].first]
- munin = "cciss-3#{array[:wwn]}-#{Regexp.last_match(1)}"
- elsif smart =~ /^.*,(\d+)$/
- munin = "#{device}-#{Regexp.last_match(1)}"
- elsif smart =~ %r{^.*,(\d+)/(\d+)$}
- munin = "#{device}-#{Regexp.last_match(1)}:#{Regexp.last_match(2)}"
- end
elsif disk[:device]
device = disk[:device].sub("/dev/", "")
smart = disk[:smart_device]
-
- if smart =~ /^.*,(\d+),(\d+),(\d+)$/
- munin = "#{device}-#{Regexp.last_match(1)}:#{Regexp.last_match(2)}:#{Regexp.last_match(3)}"
- end
end
elsif disk[:device] =~ %r{^/dev/(nvme\d+)n\d+$}
device = Regexp.last_match(1)
- munin = device
elsif disk[:device]
device = disk[:device].sub("/dev/", "")
- munin = device
end
next if device.nil?
Hash[
:device => device,
- :smart => smart,
- :munin => munin,
- :hddtemp => munin.tr("-:", "_")
+ :smart => smart
]
end
prometheus_collector "smart" do
interval "15m"
- end
-
- # Don't try and do munin monitoring of disks behind
- # an Areca controller as they only allow one thing to
- # talk to the controller at a time and smartd will
- # throw errors if it clashes with munin
- disks = disks.reject { |disk| disk[:smart]&.start_with?("areca,") }
-
- disks.each do |disk|
- munin_plugin "smart_#{disk[:munin]}" do
- target "smart_"
- conf "munin.smart.erb"
- conf_variables :disk => disk
- end
+ user "root"
+ capability_bounding_set %w[CAP_DAC_OVERRIDE CAP_SYS_ADMIN CAP_SYS_RAWIO]
+ private_devices false
+ private_users false
+ protect_clock false
end
else
service "smartd" do
end
end
-if disks.count.positive?
- munin_plugin "hddtemp_smartctl" do
- conf "munin.hddtemp.erb"
- conf_variables :disks => disks
- end
-else
- munin_plugin "hddtemp_smartctl" do
- action :delete
- conf "munin.hddtemp.erb"
- end
-end
-
-plugins = Dir.glob("/etc/munin/plugins/smart_*").map { |p| File.basename(p) } -
- disks.map { |d| "smart_#{d[:munin]}" }
-
-plugins.each do |plugin|
- munin_plugin plugin do
- action :delete
- conf "munin.smart.erb"
- end
-end
-
if File.exist?("/etc/mdadm/mdadm.conf")
mdadm_conf = edit_file "/etc/mdadm/mdadm.conf" do |line|
line.gsub!(/^MAILADDR .*$/, "MAILADDR admins@openstreetmap.org")
content mdadm_conf
end
- service "mdadm" do
+ service "mdmonitor" do
action :nothing
subscribes :restart, "file[/etc/mdadm/mdadm.conf]"
end
end
-template "/etc/modules" do
- source "modules.erb"
- owner "root"
- group "root"
- mode "644"
+file "/etc/modules" do
+ action :delete
end
-service "kmod" do
- action :nothing
- subscribes :start, "template[/etc/modules]"
+node[:hardware][:modules].each do |module_name|
+ kernel_module module_name do
+ action :install
+ not_if { kitchen? }
+ end
end
-if node[:hardware][:watchdog]
- package "watchdog"
+node[:hardware][:blacklisted_modules].each do |module_name|
+ kernel_module module_name do
+ action :blacklist
+ end
+end
+
+if watchdog_module
+ kernel_module watchdog_module do
+ action :install
+ end
- template "/etc/default/watchdog" do
- source "watchdog.erb"
+ execute "systemctl-reload" do
+ action :nothing
+ command "systemctl daemon-reload"
+ user "root"
+ group "root"
+ end
+
+ directory "/etc/systemd/system.conf.d" do
owner "root"
group "root"
- mode "644"
- variables :module => node[:hardware][:watchdog]
+ mode "755"
end
- service "watchdog" do
- action [:enable, :start]
+ template "/etc/systemd/system.conf.d/watchdog.conf" do
+ source "watchdog.conf.erb"
+ owner "root"
+ group "root"
+ mode "644"
+ notifies :run, "execute[systemctl-reload]"
end
end
notifies :run, "execute[remount-dev-shm]"
end
end
+
+prometheus_collector "ohai" do
+ interval "15m"
+ user "root"
+ proc_subset "all"
+ capability_bounding_set %w[CAP_DAC_OVERRIDE CAP_SYS_ADMIN CAP_SYS_RAWIO]
+ private_devices false
+ private_users false
+ protect_clock false
+ protect_kernel_modules false
+end
+++ /dev/null
-#!/bin/sh
-
-NAME="cciss-vol-statusd"
-STATUSFILE=/var/run/$NAME.status
-
-# Do not touch you can configure this in /etc/default/cciss-vol-statusd
-MAILTO=root # Where to report problems
-PERIOD=600 # Seconds between each check (default 10 minutes)
-REMIND=7200 # Seconds between each reminder (default 2 hours)
-ID=/dev/cciss/c0d0
-
-[ -e /etc/default/cciss-vol-statusd ] && . /etc/default/cciss-vol-statusd
-
-# Gracefully exit if the package has been removed.
-test -x /usr/bin/cciss_vol_status || exit 0
-
-while true ; do
- # Check ever $PERIOD seconds, send email on every status
- # change and repeat ever $REMIND seconds if the raid is still
- # bad.
- if (cciss_vol_status $ID); then
- BADRAID=false
- else
- BADRAID=true
- logger -t cciss-vol-statusd "detected non-optimal RAID status"
- fi
- STATUSCHANGE=false
- if [ true = "$BADRAID" ] ; then
- # RAID not OK
- (cciss_vol_status $ID) > $STATUSFILE.new
- if [ ! -f $STATUSFILE ] ; then # RAID just became broken
- STATUSCHANGE=true
- mv $STATUSFILE.new $STATUSFILE
- elif cmp -s $STATUSFILE $STATUSFILE.new ; then
- # No change. Should we send reminder?
- LASTTIME="`stat -c '%Z' $STATUSFILE`"
- NOW="`date +%s`"
- SINCELAST="`expr $NOW - $LASTTIME`"
- if [ $REMIND -le "$SINCELAST" ]; then
- # Time to send reminder
- STATUSCHANGE=true
- mv $STATUSFILE.new $STATUSFILE
- else
- rm $STATUSFILE.new
- fi
- else
- STATUSCHANGE=true
- mv $STATUSFILE.new $STATUSFILE
- fi
- else
- # RAID OK
- if [ -f $STATUSFILE ] ; then
- rm $STATUSFILE
- STATUSCHANGE=true
- fi
- fi
-
- if [ true = "$STATUSCHANGE" ]; then
- hostname="`uname -n`"
- (
- cat <<EOF
-This is a RAID status update from cciss-vol-statusd. The cciss_vol_status
-program reports that one of the RAIDs changed state:
-
-EOF
- if [ -f $STATUSFILE ] ; then
- cat $STATUSFILE
- else
- (cciss_vol_status $ID)
- fi
- echo
- echo "Report from $0 on $hostname"
- ) | mail -s "info: CCISS raid status change on $hostname" $MAILTO
- fi
-
- sleep $PERIOD
-done
--- /dev/null
+<RIBCL VERSION="2.0">
+ <LOGIN USER_LOGIN="admin" PASSWORD="password">
+ <SERVER_INFO mode="write">
+ <!-- Set Server Name -->
+ <SERVER_NAME VALUE="<%= node[:fqdn] %>"/>
+ </SERVER_INFO>
+ <SERVER_INFO mode="write">
+ <!-- 1 Operating system control mode -->
+ <!-- 2 HP Static Low Power mode -->
+ <!-- 3 HP Dynamic Power Savings mode -->
+ <!-- 4 HP Static High Performance mode -->
+ <SET_HOST_POWER_SAVER HOST_POWER_SAVER="3"/>
+ </SERVER_INFO>
+ <SERVER_INFO mode="write">
+ <!-- Set Auto Power Yes -->
+ <SERVER_AUTO_PWR VALUE="Yes"/>
+ </SERVER_INFO>
+ <SERVER_INFO mode="write">
+ <!-- Set Auto Power after random delay -->
+ <SERVER_AUTO_PWR VALUE="RANDOM"/>
+ <!-- Unset max power cap -->
+ <!-- Disable for now -->
+ <!-- SET_POWER_CAP POWER_CAP="0" -->
+ </SERVER_INFO>
+ </LOGIN>
+</RIBCL>
- ipmi
- dcmi
- chassis
+ custom_args:
+ ipmi:
+<% node[:hardware][:ipmi][:custom_args].each do |arg| -%>
+ - <%= arg %>
+<% end -%>
exclude_sensor_ids:
<% node[:hardware][:ipmi][:excluded_sensors].each do |sensor| -%>
- <%= sensor %>
--- /dev/null
+require "json"
+
+Ohai.plugin(:Lldp) do
+ provides "lldp"
+
+ collect_data(:default) do
+ lldp Mash.new
+
+ json = JSON.parse(%x(/usr/sbin/lldpctl -f json))
+
+ interfaces = if json["lldp"]["interface"].is_a?(Array)
+ json["lldp"]["interface"]
+ else
+ [json["lldp"]["interface"]]
+ end
+
+ interfaces.each do |interface|
+ interface.each do |name, details|
+ lldp[name] = details
+ end
+ end
+
+ lldp
+ end
+end
+++ /dev/null
-#!/bin/sh
-
-# DO NOT EDIT - This file is being maintained by Chef
-
-echo "$MESSAGE" | /usr/bin/mail -s "Machine Check Exception for <%= node[:fqdn] %>" admins@openstreetmap.org
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-<% node[:hardware][:modules].each do |m| -%>
-<%= m %>
-<% end -%>
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-[hddtemp_smartctl]
-env.drives <%= @disks.map { |d| d[:hddtemp] }.sort.join(" ") %>
-<% @disks.sort_by { |d| d[:hddtemp] }.each do |disk| -%>
-<% if disk[:smart] -%>
-env.type_<%= disk[:hddtemp] %> <%= disk[:smart] %>
-<% end -%>
-env.dev_<%= disk[:hddtemp] %> <%= disk[:device] %>
-<% end -%>
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-[smart_<%= @disk[:munin] %>]
-<% if @disk[:smart] -%>
-env.smartargs -H -d <%= @disk[:smart] %>
-<% else -%>
-env.smartargs -H
-<% end -%>
-env.ignoreexit 4
find_adaptec_disks(disk) if File.exist?("/usr/sbin/arcconf")
find_areca_disks(disk) if File.exist?("/opt/areca/x86_64/cli64")
- find_md_arrays(disk)
+ find_md_arrays(disk) if File.exist?("/prod/mdstat")
disk[:disks].each do |disk|
if disk[:vendor] =~ /^(BTWA|CVPR|PHDV)/ && disk[:model] == "INTEL"
array = nil
File.new("/proc/mdstat", "r").each do |line|
- if line =~ /^(md\d+) : active raid(\d+)((?: (?:sd[a-z]|nvme\d+n\d+)\d*\[\d+\](?:\([A-Z]\))*)+)$/
+ if line =~ /^(md\d+) : active raid(\d+)((?: (?:sd[a-z]\d*|nvme\d+n\d+(?:p\d+)?)\[\d+\](?:\([A-Z]\))*)+)$/
array = {
:id => devices[:arrays].count,
:device => "/dev/#{Regexp.last_match(1)}",
+ :status => "optimal",
:raid_level => Regexp.last_match(2),
:disks => []
}
- Regexp.last_match(3).scan(/ (sd[a-z]+|nvme\d+n\d+)\d*\[\d+\](?:\([A-Z]\))*/).flatten.each do |device|
- if disk = devices[:disks].find { |d| d[:device] == "/dev/#{device}" }
- disk[:arrays] << array[:id]
- array[:disks] << disk[:id]
+ Regexp.last_match(3).split(" ").each do |member|
+ if member =~ /^(sd[a-z]+|nvme\d+n\d+).*/
+ device = Regexp.last_match(1)
+
+ if disk = devices[:disks].find { |d| d[:device] == "/dev/#{device}" }
+ if member =~ /\(F\)/
+ disk[:status] = "failed"
+ elsif member =~ /\(S\)/
+ disk[:status] = "hotspare"
+ else
+ disk[:status] = "online"
+ end
+
+ disk[:arrays] << array[:id]
+ array[:disks] << disk[:id]
+ end
end
end
devices[:arrays] << array
- elsif array && line =~ /^\s+(\d+) blocks/
+ elsif array && line =~ /^\s+(\d+) blocks.*(?:\[([U_]+)\])?/
array[:size] = format_disk_size(Regexp.last_match(1).to_i)
+ array[:status] = "degraded" if Regexp.last_match(2) =~ /_/
+ elsif array && line =~ /^\s+\[.*\]\s+(\S+)\s+=/
+ case Regexp.last_match(1)
+ when "recovery" then array[:status] = "rebuilding"
+ when "resync" then array[:status] = "rebuilding"
+ when "checking" then array[:status] = "checking"
+ end
end
end
end
disk = nil
IO.popen(%w(ssacli controller all show config detail)).each do |line|
+ next unless line.valid_encoding?
+
if line =~ /^Smart (?:Array|HBA) (\S+) /
controller = {
:id => devices[:controllers].count,
+ :type => "hp",
:model => Regexp.last_match(1),
:arrays => [],
:disks => []
when "Hardware Revision" then controller[:hardware_version] = Regexp.last_match(2)
when "Firmware Version" then controller[:firmware_version] = Regexp.last_match(2)
when "PCI Address (Domain:Bus:Device.Function)" then controller[:pci_slot] = Regexp.last_match(2)
+ when "Battery/Capacitor Status" then controller[:battery_status] = Regexp.last_match(2).split.first.downcase
end
elsif controller && line =~ /^ Logical Drive: (\d+)$/
array = {
array[:disks] << disk[:id]
elsif disk && line =~ /^ (\S[^:]+):\s+(.*\S)\s*$/
case Regexp.last_match(1)
+ when "Status" then disk[:status] = Regexp.last_match(2)
+ when "Drive Type" then disk[:drive_type] = Regexp.last_match(2)
when "Interface Type" then disk[:interface] = Regexp.last_match(2)
when "Size" then disk[:size] = Regexp.last_match(2)
when "Rotational Speed" then disk[:rpm] = Regexp.last_match(2)
when "Serial Number" then disk[:serial_number] = Regexp.last_match(2)
when "Model" then disk[:model] = Regexp.last_match(2)
end
+ elsif array && line =~ /^ Status:\s+(.*\S)\s*$/
+ case Regexp.last_match(1)
+ when "OK" then array[:status] = "optimal"
+ when "Interim Recovery Mode" then array[:status] = "degraded"
+ else array[:status] = "unknown"
+ end
elsif array && line =~ /^ (\S[^:]+):\s+(.*\S)\s*$/
case Regexp.last_match(1)
when "Size" then array[:size] = Regexp.last_match(2)
when "Fault Tolerance" then array[:raid_level] = Regexp.last_match(2)
+ when "Status" then array[:status] = Regexp.last_match(2)
when "Disk Name" then array[:device] = Regexp.last_match(2).strip
when "Mount Points" then array[:mount_point] = Regexp.last_match(2).split.first
when "Unique Identifier" then array[:wwn] = Regexp.last_match(2)
end
devices[:disks].each do |disk|
- disk[:smart_device] = "cciss,#{disks.find_index(disk[:location])}"
+ controller = disk[:controller]
+
+ next unless devices[:controllers][controller][:type] == "hp"
+
+ disk[:smart_device] = "cciss,#{disks.find_index(disk[:location])}"
+
+ if disk[:status] == "Failed"
+ disk[:status] = "failed"
+ elsif disk[:status] == "Predictive Failure"
+ disk[:status] = "failed"
+ elsif disk[:status] == "OK" && disk[:drive_type] == "Data Drive"
+ disk[:status] = "online"
+ elsif disk[:status] == "OK" && disk[:drive_type] == "Spare Drive"
+ disk[:status] = "hotspare"
+ elsif disk[:drive_type] == "Unassigned Drive"
+ disk[:status] = "unconfigured"
+ else
+ disk[:status] = "unknown"
+ end
+
+ disk.delete(:drive_type)
end
end
def find_megaraid_disks(devices)
controllers = []
arrays = []
+ disks = []
controller = nil
array = nil
if line =~ /^PCI information for Controller (\d+)$/
controller = {
:id => devices[:controllers].count,
+ :type => "megaraid",
:arrays => [],
:disks => []
}
devices[:controllers] << controller
controllers << controller
- elsif line =~ /^Bus Number\s+:\s+(\d+)$/
+ elsif line =~ /^Bus Number\s+:\s+([0-9a-f]+)$/i
controller[:pci_slot] = format "0000:%02x", Integer("0x#{Regexp.last_match(1)}")
- elsif line =~ /^Device Number\s+:\s+(\d+)$/
+ elsif line =~ /^Device Number\s+:\s+([0-9a-f]+)$/i
controller[:pci_slot] = format "%s:%02x", controller[:pci_slot], Integer("0x#{Regexp.last_match(1)}")
- elsif line =~ /^Function Number\s+:\s+(\d+)$/
+ elsif line =~ /^Function Number\s+:\s+([0-9a-f]+)$/i
controller[:pci_slot] = format "%s.%01x", controller[:pci_slot], Integer("0x#{Regexp.last_match(1)}")
end
end
devices[:disks] << disk
controller[:disks] << disk[:id]
array[:disks] << disk[:id]
- elsif disk && line =~ /^Firmware state:\s+(.*\S)\s*$/
- Regexp.last_match(1).split(/,\s*/).each do |state|
- case state
- when "Unconfigured(bad)" then disk[:status] = "unconfigured"
- when "Online" then disk[:status] = "online"
- when "Hotspare" then disk[:status] = "hotspare"
- when "Failed" then disk[:status] = "failed"
- when "Spun Up" then disk[:state] = "spun_up"
- when "Spun down" then disk[:state] = "spun_down"
- end
+
+ disks << disk
+ elsif disk && line =~ /^Firmware state:\s+(\S.*)$/
+ status, state = Regexp.last_match(1).split(/,\s*/)
+ case status
+ when "Unconfigured(good)" then disk[:status] = "unconfigured"
+ when "Unconfigured(bad)" then disk[:status] = "unconfigured"
+ when "Hotspare" then disk[:status] = "hotspare"
+ when "Offline" then disk[:status] = "offline"
+ when "Online" then disk[:status] = "online"
+ when "Rebuild" then disk[:status] = "rebuilding"
+ when "Failed" then disk[:status] = "failed"
+ when "Copyback" then disk[:status] = "rebuilding"
+ else disk[:status] = "unknown"
+ end
+ case state
+ when "Spun Up" then disk[:state] = "spun_up"
+ when "Spun down" then disk[:state] = "spun_down"
+ else disk[:state] = "unknown"
end
elsif disk && line =~ /^(\S.*\S)\s*:\s+(\S.*)$/
case Regexp.last_match(1)
- when "Device Id" then disk[:smart_device] = "megaraid,#{Regexp.last_match(2)}"
+ when "Device Id" then disk[:device_id] = Regexp.last_match(2)
when "WWN" then disk[:wwn] = Regexp.last_match(2)
when "PD Type" then disk[:interface] = Regexp.last_match(2)
when "Raw Size" then disk[:size] = memory_to_disk_size(Regexp.last_match(2).sub(/\s*\[.*\]$/, ""))
when "Inquiry Data" then disk[:vendor], disk[:model], disk[:serial_number] = Regexp.last_match(2).split
end
+ elsif array && line =~ /^State\s*:\s+(.*\S)\s*$/
+ case Regexp.last_match(1)
+ when "Partially Degraded" then array[:status] = "degraded"
+ when "Degraded" then array[:status] = "degraded"
+ when "Optimal" then array[:status] = "optimal"
+ when "Consistency Check" then array[:status] = "checking"
+ when "Background Initialization" then array[:status] = "initialising"
+ when "Initialization" then array[:status] = "initialising"
+ when "Reconstruction" then array[:status] = "rebuilding"
+ else array[:status] = "unknown"
+ end
elsif array && line =~ /^(\S.*\S)\s*:\s+(\S.*)$/
case Regexp.last_match(1)
when "RAID Level" then array[:raid_level] = Regexp.last_match(2).scan(/Primary-(\d+)/).first.first
controller = controllers[Regexp.last_match(1).to_i]
elsif controller && line =~ /^Enclosure Device ID: \d+$/
disk = {
- :controller => controller[:id]
+ :controller => controller[:id],
+ :arrays => []
}
elsif disk && line =~ /^WWN:\s+(\S+)$/
unless devices[:disks].find { |d| d[:wwn] == Regexp.last_match(1) }
disk[:wwn] = Regexp.last_match(1)
devices[:disks] << disk
+
+ disks << disk
end
- elsif disk && line =~ /^Firmware state:\s+(.*\S)\s*$/
- Regexp.last_match(1).split(/,\s*/).each do |state|
- case state
- when "Unconfigured(bad)" then disk[:status] = "unconfigured"
- when "Online" then disk[:status] = "online"
- when "Hotspare" then disk[:status] = "hotspare"
- when "Failed" then disk[:status] = "failed"
- when "Spun Up" then disk[:state] = "spun_up"
- when "Spun down" then disk[:state] = "spun_down"
- end
+ elsif disk && line =~ /^Firmware state:\s+(\S.*)$/
+ status, state = Regexp.last_match(1).split(/,\s*/)
+ case status
+ when "Unconfigured(good)" then disk[:status] = "unconfigured"
+ when "Unconfigured(bad)" then disk[:status] = "unconfigured"
+ when "Hotspare" then disk[:status] = "hotspare"
+ when "Offline" then disk[:status] = "offline"
+ when "Online" then disk[:status] = "online"
+ when "Rebuild" then disk[:status] = "rebuilding"
+ when "Failed" then disk[:status] = "failed"
+ when "Copyback" then disk[:status] = "rebuilding"
+ else disk[:status] = "unknown"
+ end
+ case state
+ when "Spun Up" then disk[:state] = "spun_up"
+ when "Spun down" then disk[:state] = "spun_down"
+ else disk[:state] = "unknown"
end
elsif disk && line =~ /^(\S.*\S)\s*:\s+(\S.*)$/
case Regexp.last_match(1)
- when "Device Id" then disk[:smart_device] = "megaraid,#{Regexp.last_match(2)}"
+ when "Device Id" then disk[:device_id] = Regexp.last_match(2)
when "PD Type" then disk[:interface] = Regexp.last_match(2)
when "Raw Size" then disk[:size] = memory_to_disk_size(Regexp.last_match(2).sub(/\s*\[.*\]$/, ""))
when "Inquiry Data" then disk[:vendor], disk[:model], disk[:serial_number] = Regexp.last_match(2).split
controller[:device] = "/dev/#{File.basename(device)}"
end
end
+
+ disks.each do |disk|
+ controller = devices[:controllers][disk[:controller]]
+
+ if id = disk.delete(:device_id)
+ if device = Dir.glob("/sys/bus/pci/devices/#{controller[:pci_slot]}/host*/target0:0:#{id}/0:0:#{id}:0/block/sd*").first
+ disk[:device] = "/dev/#{File.basename(device)}"
+ else
+ disk[:smart_device] = "megaraid,#{id}"
+ end
+ end
+ end
end
def find_mpt1_disks(devices)
if line =~ /^\/proc\/mpt\/ioc(\d+)\s+LSI Logic\s+(\S+)\s+/
controller = {
:id => devices[:controllers].count,
+ :type => "mpt1",
:model => Regexp.last_match(1),
:arrays => [],
:disks => []
next unless line =~ /^\s+(\d+)\s+(\S+)\s+\h+h\s+\h+h\s+(\S+)\s+\h+h\s+\h+h\s*$/
controllers[Regexp.last_match(1).to_i] = {
:id => devices[:controllers].count,
+ :type => "mpt2",
:model => Regexp.last_match(2),
:pci_slot => Regexp.last_match(3).sub(/^(\h{2})h:(\h{2})h:(\h{2})h:0(\h)h$/, "00\\1:\\2:\\3.\\4"),
:arrays => [],
controller[:disks] << disk[:id]
disks << disk
+ elsif disk && line =~ /^ State\s+:\s+(.*\S)\s*$/
+ Regexp.last_match(1).split(/,\s*/).each do |state|
+ case state
+ when "Online (ONL)" then disk[:status] = "online"
+ when "Hot Spare (HSP)" then disk[:status] = "hotspare"
+ when "Ready (RDY)" then disk[:status] = "unconfigured"
+ when "Available (AVL)" then disk[:status] = "unconfigured"
+ when "Failed (FLD)" then disk[:status] = "failed"
+ when "Missing (MIS)" then disk[:status] = "missing"
+ when "Standby (SBY)" then disk[:status] = "unconfigured"
+ when "Out of Sync (OSY)" then disk[:status] = "degraded"
+ when "Degraded (DGD)" then disk[:status] = "degraded"
+ when "Rebuilding (RBLD)" then disk[:status] = "rebuilding"
+ when "Optimal (OPT)" then disk[:status] = "online"
+ else disk[:status] = "unknown"
+ end
+ end
elsif disk && line =~ /^ (\S.*\S)\s+:\s+(.*\S)\s*$/
case Regexp.last_match(1)
when "Enclosure #" then disk[:location] = Regexp.last_match(2)
end
elsif array && line =~ /^ PHY\[\d+\] Enclosure#\/Slot#\s+:\s+(\d+:\d+)\s*$/
array[:disks] << Regexp.last_match(1)
+ elsif array && line =~ /^ Status of volume\s+:\s+(.*\S)\s*$/
+ Regexp.last_match(1).split(/,\s*/).each do |state|
+ case state
+ when "Okay (OKY)" then array[:status] = "optimal"
+ when "Degraded (DGD)" then array[:status] = "degraded"
+ when "Failed (FLD)" then array[:status] = "failed"
+ when "Missing (MIS)" then array[:status] = "missing"
+ when "Initializing (INIT)" then array[:status] = "initialising"
+ when "Online (ONL)" then array[:status] = "optimal"
+ else array[:status] = "unknown"
+ end
+ end
elsif array && line =~ /^ (\S.*\S)\s+:\s+(.*\S)\s*$/
case Regexp.last_match(1)
when "Volume wwid" then array[:device] = find_sas_device(Regexp.last_match(2))
controller = {
:id => devices[:controllers].count,
:number => controller_number,
+ :type => "adaptec",
:arrays => [],
:disks => []
}
elsif disk && line =~ /^ Reported Channel,Device\(T:L\)\s*:\s+(\d+),(\d+)\(\d+:0\)\s*$/
disk[:channel_number] = Regexp.last_match(1)
disk[:device_number] = Regexp.last_match(2)
+ elsif disk && line =~ /^ State\s*:\s+(\S.*\S)\s*$/
+ case Regexp.last_match(1)
+ when "Online" then disk[:status] = "online"
+ when "Online (JBOD)" then disk[:status] = "online"
+ when "Hot Spare" then disk[:status] = "hotspare"
+ when "Ready" then disk[:status] = "unconfigured"
+ when "Global Hot-Spare" then disk[:status] = "hostspare"
+ when "Dedicated Hot-Spare" then disk[:status] = "hotspare"
+ else disk[:status] = "unknown"
+ end
elsif disk && line =~ /^ (\S.*\S)\s*:\s+(\S.*\S)\s*$/
case Regexp.last_match(1)
when "Reported Location" then disk[:location] = Regexp.last_match(2)
end
elsif array && line =~ / Present \(.*((?:Connector|Enclosure):\d+,\s*(?:Device|Slot):\d+)\) /
array[:disks] << Regexp.last_match(1).tr(":", " ").gsub(/,\s*/, ", ")
+ elsif array && line =~ /^ Status of Logical Device\s*:\s+(\S.*\S)\s*$/
+ case Regexp.last_match(1)
+ when "Optimal" then array[:status] = "optimal"
+ else array[:status] = "unknown"
+ end
elsif array && line =~ /^ (\S.*\S)\s*:\s+(\S.*\S)\s*$/
case Regexp.last_match(1)
when "RAID level" then array[:raid_level] = Regexp.last_match(2)
def find_areca_disks(devices)
controller = {
:id => devices[:controllers].count,
+ :type => "areca",
:arrays => [],
:disks => []
}
device = Dir.glob("/sys/bus/pci/devices/#{pci_slot}/host*/target*:0:0/0:#{channel}:#{id}:#{lun}/block/*").first
array[:device] = "/dev/#{File.basename(device)}"
+ elsif line =~ /^Volume State\s+:\s+(.*\S)\s*$/
+ case Regexp.last_match(1)
+ when "Normal" then array[:status] = "optimal"
+ else array[:status] = "unknown"
+ end
elsif line =~ /^(\S.*\S)\s+:\s+(.*\S)\s*$/
case Regexp.last_match(1)
when "Volume Set Name" then array[:volume_set] = Regexp.last_match(2)
disk[:smart_device] = "areca,#{Regexp.last_match(1)}"
elsif line =~ /^Device Location\s+:\s+Enclosure#(\d+) Slot#?\s*0*(\d+)\s*$/i
disk[:smart_device] = "areca,#{Regexp.last_match(2)}/#{Regexp.last_match(1)}"
+ elsif line =~ /^Device State\s+:\s+(.*\S)\s*$/
+ case Regexp.last_match(1)
+ when "NORMAL" then disk[:status] = "online"
+ else disk[:status] = "unknown"
+ end
elsif line =~ /^(\S.*\S)\s+:\s+(.*\S)\s*$/
case Regexp.last_match(1)
when "Model Name" then disk[:vendor], disk[:model] = Regexp.last_match(2).split
+++ /dev/null
-MAILTO="admins@openstreetmap.org"
-REMIND="86400"
-<% unless @devices.empty? -%>
-ID="<%= @devices.sort.uniq.map { |d| "/dev/#{d}" }.join(" ") %>"
-<% end -%>
<% elsif disk[:device] =~ /nvme/ -%>
/dev/<%= disk[:device] %>|nvme
<% else -%>
-/dev/<%= disk[:device] %>|sat
+/dev/<%= disk[:device] %>|auto
<% end -%>
<% end -%>
# DO NOT EDIT - This file is being maintained by Chef
-[df*]
-env.exclude_re ^/run/user/
+[Manager]
+RuntimeWatchdogSec=60s
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-# Start watchdog at boot time? 0 or 1
-run_watchdog=1
-# Load module before starting watchdog
-watchdog_module="<%= @module %>"
-# Specify additional watchdog options here (see manpage).
version "1.0.0"
supports "ubuntu"
-depends "apache"
+depends "podman"
# limitations under the License.
#
-include_recipe "apache"
+include_recipe "podman::apache"
-ssl_certificate "hot.openstreetmap.org" do
- domains ["hot.openstreetmap.org", "hot.osm.org"]
- notifies :reload, "service[apache2]"
-end
-
-apache_site "hot.openstreetmap.org" do
- template "apache.erb"
+podman_site "hot.openstreetmap.org" do
+ image "ghcr.io/openstreetmap/hot.openstreetmap.org-website:latest"
+ aliases ["hot.osm.org"]
end
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-<VirtualHost *:80>
- ServerName hot.openstreetmap.org
- ServerAlias hot.osm.org
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/hot.openstreetmap.org-access.log combined
- ErrorLog /var/log/apache2/hot.openstreetmap.org-error.log
-
- RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
- RedirectPermanent / https://www.hotosm.org/
-</VirtualHost>
-
-<VirtualHost *:443>
- ServerName hot.openstreetmap.org
- ServerAlias hot.osm.org
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/hot.openstreetmap.org-access.log combined
- ErrorLog /var/log/apache2/hot.openstreetmap.org-error.log
-
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/hot.openstreetmap.org.pem
- SSLCertificateKeyFile /etc/ssl/private/hot.openstreetmap.org.key
-
- RedirectPermanent / https://www.hotosm.org/
-</VirtualHost>
-name "timescaledb"
+name "ideditor"
maintainer "OpenStreetMap Administrators"
maintainer_email "admins@openstreetmap.org"
license "Apache-2.0"
-description "Installs and configures timescaledb"
+description "Configures ideditor.com web site"
version "1.0.0"
supports "ubuntu"
-depends "apache"
-depends "apt"
-depends "postgresql"
+depends "podman"
--- /dev/null
+#
+# Cookbook:: ideditor
+# Recipe:: default
+#
+# Copyright:: 2022, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "podman::apache"
+
+podman_site "preview.ideditor.com" do
+ image "ghcr.io/openstreetmap/preview.ideditor.com-website:latest"
+end
version "1.0.0"
supports "ubuntu"
-depends "nginx"
+depends "accounts"
depends "git"
-depends "systemd"
+depends "nginx"
+depends "podman"
depends "ssl"
+depends "systemd"
# limitations under the License.
#
+include_recipe "accounts"
include_recipe "nginx"
include_recipe "git"
-# Imagery gdal Requirements
-package "gdal-bin"
-# python-gdal - disable while broken in gis unstable repo
+# Imagery gdal and proj requirements
+package %w[
+ gdal-bin
+ python3-gdal
+ proj-bin
+]
-# Imagery MapServer + Mapcache Requirements
+# Imagery MapServer + Mapcache requirements
package %w[
cgi-mapserver
mapcache-cgi
mapcache-tools
]
-# Mapserver via Nginx requires as fastcgi spawner
+# Mapserver via nginx requires as fastcgi spawner
package %w[
spawn-fcgi
multiwatch
recursive true
end
-directory "/srv/imagery/common/ostn02-ntv2-data" do
- owner "root"
- group "root"
- mode "755"
+# Pre-download uk_os_OSTN15_NTv2_OSGBtoETRS.tif used for EPSG:27700 conversions
+execute "uk_os_OSTN15_NTv2_OSGBtoETRS.tif" do
+ command "projsync --file uk_os_OSTN15_NTv2_OSGBtoETRS.tif --system-directory"
+ not_if { ::File.exist?("/usr/share/proj/uk_os_OSTN15_NTv2_OSGBtoETRS.tif") }
end
-remote_file "#{Chef::Config[:file_cache_path]}/ostn02-ntv2-data.zip" do
- source "https://www.ordnancesurvey.co.uk/docs/gps/ostn02-ntv2-data.zip"
- not_if { ::File.exist?("/srv/imagery/common/ostn02-ntv2-data/OSTN02_NTv2.gsb") }
-end
-
-execute "unzip-ostn02-ntv2-data" do
- command "unzip -q #{Chef::Config[:file_cache_path]}/ostn02-ntv2-data.zip"
- cwd "/srv/imagery/common/ostn02-ntv2-data"
- user "root"
- group "root"
- not_if { ::File.exist?("/srv/imagery/common/ostn02-ntv2-data/OSTN02_NTv2.gsb") }
-end
-
-nginx_site "default" do
- template "nginx_default.conf.erb"
- directory "/srv/imagery/default"
-end
+# nginx_site "default" do
+# template "nginx_default.conf.erb"
+# directory "/srv/imagery/default"
+# end
systemd_tmpfile "/run/mapserver-fastcgi" do
type "d"
owner "imagery"
group "imagery"
mode "0755"
+ not_if { kitchen? }
end
# limitations under the License.
#
+include_recipe "imagery"
+
imagery_site "ea.openstreetmap.org.uk" do
title "OpenStreetMap - Environment Agency OpenData"
bbox [[51.35, -2.2], [52.65, 0.10]]
copyright "Contains OS data © Crown copyright and database right 2021"
background_colour "213 244 248" # OS OpenMap Local Water Blue
extension "os_om_local_png"
- url_aliases ["/om-local-2021-04", "/om-local"]
+end
+
+imagery_layer "gb_os_om_local_2021_10" do
+ site "os.openstreetmap.org"
+ title "OS OpenMap Local - October 2021"
+ projection "EPSG:27700"
+ source "/data/imagery/gb/openmap-local/2021-10/os-openmap-local-2021-10.vrt"
+ copyright "Contains OS data © Crown copyright and database right 2021"
+ background_colour "213 244 248" # OS OpenMap Local Water Blue
+ extension "os_om_local_png"
+end
+
+imagery_layer "gb_os_om_local_2022_04" do
+ site "os.openstreetmap.org"
+ title "OS OpenMap Local - April 2022"
+ projection "EPSG:27700"
+ source "/data/imagery/gb/openmap-local/2022-04/os-openmap-local-2022-04.vrt"
+ copyright "Contains OS data © Crown copyright and database right 2022"
+ background_colour "213 244 248" # OS OpenMap Local Water Blue
+ extension "os_om_local_png"
+end
+
+imagery_layer "gb_os_om_local_2022_10" do
+ site "os.openstreetmap.org"
+ title "OS OpenMap Local - October 2022"
+ projection "EPSG:27700"
+ source "/data/imagery/gb/openmap-local/2022-10/os-openmap-local-2022-10.vrt"
+ copyright "Contains OS data © Crown copyright and database right 2022"
+ background_colour "213 244 248" # OS OpenMap Local Water Blue
+ extension "os_om_local_png"
+end
+
+imagery_layer "gb_os_om_local_2023_04" do
+ site "os.openstreetmap.org"
+ title "OS OpenMap Local - April 2023"
+ projection "EPSG:27700"
+ source "/data/imagery/gb/openmap-local/2023-04/os-openmap-local-2023-04.vrt"
+ copyright "Contains OS data © Crown copyright and database right 2023"
+ background_colour "213 244 248" # OS OpenMap Local Water Blue
+ extension "os_om_local_png"
+end
+
+imagery_layer "gb_os_om_local_2023_10" do
+ site "os.openstreetmap.org"
+ title "OS OpenMap Local - October 2023"
+ projection "EPSG:27700"
+ source "/data/imagery/gb/openmap-local/2023-10/os-openmap-local-2023-10.vrt"
+ copyright "Contains OS data © Crown copyright and database right 2023"
+ background_colour "213 244 248" # OS OpenMap Local Water Blue
+ extension "os_om_local_png"
+ url_aliases ["/om-local-2023-10", "/om-local"]
default_layer true
end
imagery_layer "mappers_delight_lidar_dem_2019" do
site "lidar-hillshade-2019.openstreetmap.lu"
- projection "EPSG:3857"
- source "/data/imagery/lu/lidar-hillshade/dem-3857.tif"
- max_zoom 20
- title "OpenStreetMap.lu Mapper's Delight 2019 Lidar DEM"
- copyright 'Lidar data 2019 <a href="https://data.public.lu/fr/datasets/lidar-2019-releve-3d-du-territoire-luxembourgeois">Administration du Cadastre et de la Topographie Luxembourg</a>, DEM <a href="https://twitter.com/grischard">Guillaume Rischard</a>, CC0'
+ action :delete
end
imagery_layer "mappers_delight_lidar_hillshade_2019_reprojected" do
imagery_layer "ana_dtm_2017" do
site "ana-dtm-2017.openstreetmap.lu"
- projection "EPSG:3857"
- source "/data/imagery/lu/LUREF_NGL/lu_color_relief-epsg3857-compress.tif"
- max_zoom 21
- title "DTM"
- copyright '© 2017 <a href="https://data.public.lu/fr/datasets/digital-terrain-model-high-dem-resolution/">Administration de la Navigation Aérienne Luxembourg</a>, CC0'
+ action :delete
end
imagery_layer "ana_dtm_2017_hillshading" do
site "ana-dtm-2017.openstreetmap.lu"
- projection "EPSG:3857"
- source "/data/imagery/lu/LUREF_NGL/lu_hillshade_2017-epsg-3857-compress.tif"
- max_zoom 21
- title "DTM Hillshading (single light source)"
- copyright '© 2017 <a href="https://data.public.lu/fr/datasets/digital-terrain-model-high-dem-resolution/">Administration de la Navigation Aérienne Luxembourg</a>, CC0'
+ action :delete
end
imagery_layer "ana_dtm_2017_hillshading_multi" do
--- /dev/null
+#
+# Cookbook:: imagery
+# Recipe:: tiler
+#
+# Copyright:: 2023, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "imagery"
+include_recipe "podman"
+
+directory "/store/imagery" do
+ owner "root"
+ group "root"
+ mode "755"
+ recursive true
+end
+
+# FIXME: until upstream supports arm64 images: https://github.com/developmentseed/titiler/pull/740
+container_image = if arm?
+ "ghcr.io/firefishy/titiler:latest"
+ else
+ "ghcr.io/developmentseed/titiler:latest"
+ end
+
+podman_service "titiler" do
+ description "Container service for titiler"
+ image container_image
+ ports 8080 => 8080
+ volume "/store/imagery" => "/store/imagery"
+ environment :PORT => 8080,
+ :WORKERS_PER_CORE => 1,
+ :GDAL_CACHEMAX => 200,
+ :GDAL_DISABLE_READDIR_ON_OPEN => "EMPTY_DIR",
+ :GDAL_INGESTED_BYTES_AT_OPEN => 32768,
+ :GDAL_HTTP_MERGE_CONSECUTIVE_RANGES => "YES",
+ :GDAL_HTTP_MULTIPLEX => "YES",
+ :GDAL_HTTP_VERSION => 2,
+ :VSI_CACHE => "TRUE",
+ :VSI_CACHE_SIZE => 5000000,
+ :TITILER_API_ROOT_PATH => "/api/v1/titiler",
+ :FORWARDED_ALLOW_IPS => "*" # https://docs.gunicorn.org/en/latest/settings.html#forwarded-allow-ips
+end
+
+directory "/var/cache/nginx-cache" do
+ owner "www-data"
+ group "www-data"
+ mode "755"
+end
+
+ssl_certificate "tiler.openstreetmap.org" do
+ domains "tiler.openstreetmap.org"
+ notifies :reload, "service[nginx]"
+end
+
+nginx_site "tiler.openstreetmap.org" do
+ template "nginx_titiler.conf.erb"
+ variables :aliases => ["tiler.osm.org"]
+end
--- /dev/null
+#
+# Cookbook:: imagery
+# Recipe:: za_ngi_aerial
+#
+# Copyright:: 2024, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "imagery::tiler"
+
+imagery_site "aerial.openstreetmap.org.za" do
+ title "OpenStreetMap - NGI - Aerial Imagery"
+ aliases ["aerial.osm.org.za"]
+ bbox [[-35.12, 16.23], [-22.1, 33.18]]
+ uses_tiler true
+end
+
+imagery_layer "ngi-aerial" do
+ site "aerial.openstreetmap.org.za"
+ uses_tiler true
+ title "NGI Aerial 25cm/50cm"
+ source "file:///store/imagery/za/za-25cm/mosaic-tiler-file.json"
+ copyright 'State Copyright © 2024 <a href="http://www.ngi.gov.za/">Chief Directorate: National Geo-spatial Information</a>'
+ max_zoom 20
+ extension "jpg"
+ default_layer true
+ url_aliases ["/ngi-aerial"]
+end
property :revision, Integer, :default => 0
property :overlay, [true, false], :default => false
property :default_layer, [true, false], :default => false
+property :uses_tiler, [true, false], :default => false
action :create do
file "/srv/imagery/layers/#{new_resource.site}/#{new_resource.layer}.yml" do
mode "644"
content YAML.dump(:name => new_resource.layer,
:title => new_resource.title || new_resource.layer,
- :url => "//{s}.#{new_resource.site}/layer/#{new_resource.layer}/{z}/{x}/{y}.png",
+ :url => "//#{new_resource.site}/layer/#{new_resource.layer}/{z}/{x}/{y}.#{new_resource.extension}".gsub(/\.(os_sv_png|os_sv_diff_png|os_om_local_png)$/, ".png"),
:attribution => new_resource.copyright,
:default => new_resource.default_layer,
:maxZoom => new_resource.max_zoom,
group "root"
mode "644"
variables new_resource.to_hash
+ not_if { new_resource.uses_tiler }
end
directory "/srv/imagery/nginx/#{new_resource.site}" do
property :title, String, :required => [:create]
property :aliases, [String, Array], :default => []
property :bbox, Array, :required => [:create]
+property :uses_tiler, [true, false], :default => false
action :create do
directory "/srv/#{new_resource.site}" do
end
layers = Dir.glob("/srv/imagery/layers/#{new_resource.site}/*.yml").collect do |path|
- YAML.safe_load(::File.read(path), [Symbol])
+ YAML.safe_load(::File.read(path), :permitted_classes => [Symbol])
end
declare_resource :template, "/srv/#{new_resource.site}/imagery.js" do
base_domains = [new_resource.site] + Array(new_resource.aliases)
tile_domains = base_domains.flat_map { |d| [d, "a.#{d}", "b.#{d}", "c.#{d}"] }
- %w[0 1 2 3 4 5 6 7].each do |index|
- systemd_service "mapserv-fcgi-#{new_resource.site}-#{index}" do
- description "Map server for #{new_resource.site} layer"
- environment "MS_MAP_PATTERN" => "^/srv/imagery/mapserver/",
- "MS_DEBUGLEVEL" => "0",
- "MS_ERRORFILE" => "stderr",
- "GDAL_CACHEMAX" => "512"
- limit_nofile 16384
- limit_cpu 180
- memory_high "512M"
- memory_max "1G"
- user "imagery"
- group "imagery"
- exec_start_pre "/bin/rm -f /run/mapserver-fastcgi/layer-#{new_resource.site}-#{index}.socket"
- exec_start "/usr/bin/spawn-fcgi -n -b 8192 -s /run/mapserver-fastcgi/layer-#{new_resource.site}-#{index}.socket -M 0666 -P /run/mapserver-fastcgi/layer-#{new_resource.site}-#{index}.pid -- /usr/lib/cgi-bin/mapserv"
- private_tmp true
- private_devices true
- private_network true
- protect_system "full"
- protect_home true
- no_new_privileges true
- restart "always"
- pid_file "/run/mapserver-fastcgi/layer-#{new_resource.site}-#{index}.pid"
- end
-
- service "mapserv-fcgi-#{new_resource.site}-#{index}" do
- provider Chef::Provider::Service::Systemd
- action [:enable, :start]
- supports :status => true, :restart => true, :reload => false
- subscribes :restart, "systemd_service[mapserv-fcgi-#{new_resource.site}-#{index}]"
- end
+ systemd_service "mapserv-fcgi-#{new_resource.site}" do
+ description "Map server for #{new_resource.site} layer"
+ environment "MS_MAP_PATTERN" => "^/srv/imagery/mapserver/",
+ "MS_DEBUGLEVEL" => "0",
+ "MS_ERRORFILE" => "stderr",
+ "GDAL_CACHEMAX" => "512"
+ limit_nofile 16384
+ memory_high "1G"
+ memory_max "4G"
+ user "imagery"
+ group "imagery"
+ exec_start "/usr/bin/multiwatch -f 8 --signal=TERM -- /usr/lib/cgi-bin/mapserv"
+ standard_input "socket"
+ sandbox true
+ restrict_address_families "AF_UNIX"
+ # Terminate service after 30mins. Service is socket activated
+ runtime_max_sec 1800
+ not_if { new_resource.uses_tiler }
+ end
+
+ systemd_socket "mapserv-fcgi-#{new_resource.site}" do
+ description "Map server for #{new_resource.site} layer socket"
+ socket_user "imagery"
+ socket_group "imagery"
+ listen_stream "/run/mapserver-fastcgi/layer-#{new_resource.site}.socket"
+ not_if { new_resource.uses_tiler }
+ end
+
+ # Ensure service is stopped because otherwise the socket cannot reload
+ service "mapserv-fcgi-#{new_resource.site}" do
+ provider Chef::Provider::Service::Systemd
+ action :nothing
+ subscribes :stop, "systemd_service[mapserv-fcgi-#{new_resource.site}]"
+ subscribes :stop, "systemd_socket[mapserv-fcgi-#{new_resource.site}]"
+ not_if { new_resource.uses_tiler }
+ end
+
+ systemd_unit "mapserv-fcgi-#{new_resource.site}.socket" do
+ action [:enable, :start]
+ subscribes :restart, "systemd_socket[mapserv-fcgi-#{new_resource.site}]"
+ not_if { new_resource.uses_tiler }
end
ssl_certificate new_resource.site do
end
action :delete do
- %w[0 1 2 3 4 5 6 7].each do |index|
- service "mapserv-fcgi-#{new_resource.site}-#{index}" do
- provider Chef::Provider::Service::Systemd
- action [:stop, :disable]
- end
-
- systemd_service "mapserv-fcgi-#{new_resource.site}-#{index}" do
- action :delete
- end
+ service "mapserv-fcgi-#{new_resource.site}" do
+ provider Chef::Provider::Service::Systemd
+ action [:stop, :disable]
+ not_if { new_resource.uses_tiler }
+ end
+
+ systemd_service "mapserv-fcgi-#{new_resource.site}" do
+ action :delete
+ not_if { new_resource.uses_tiler }
end
nginx_site new_resource.site do
+<% require 'uri' %>
function createMap(divName) {
// Create a map
var map = L.map(divName, {
<% @layers.sort_by { |layer| layer[:name] }.each do |layer| -%>
// Create <%= layer[:name] %> layer
- var <%= layer[:name] %> = L.tileLayer(<%= layer[:url].to_json %>, {
+ var <%= layer[:name].gsub("-", "_") %> = L.tileLayer(<%= layer[:url].to_json %>, {
attribution: <%= layer[:attribution].to_json %>,
maxZoom: <%= layer[:maxZoom].to_json %>
});
// Add <%= layer[:name] %> to layer switcher
<% if layer[:overlay] -%>
- layers.addOverlay(<%= layer[:name] %>, <%= layer[:title].to_json %>);
+ layers.addOverlay(<%= layer[:name].gsub("-", "_") %>, <%= layer[:title].to_json %>);
<% else %>
- layers.addBaseLayer(<%= layer[:name] %>, <%= layer[:title].to_json %>);
+ layers.addBaseLayer(<%= layer[:name].gsub("-", "_") %>, <%= layer[:title].to_json %>);
<% end -%>
<% if layer[:default] -%>
// Add <%= layer[:name] %> to map
- <%= layer[:name] %>.addTo(map);
+ <%= layer[:name].gsub("-", "_") %>.addTo(map);
<% end -%>
<% end -%>
<title><%= @title %></title>
<link rel="stylesheet" href="imagery.css" type="text/css" media="all" />
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/leaflet.min.css" integrity="sha512-1xoFisiGdy9nvho8EgXuXvnpR5GAMSjFwp40gSRE3NwdUdIMIKuPa7bqoUhLD0O/5tPNhteAsE5XyyMi5reQVA==" crossorigin="anonymous" />
- <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/leaflet.min.js" integrity="sha512-SeiQaaDh73yrb56sTW/RgVdi/mMqNeM2oBwubFHagc5BkixSpP1fvqF47mKzPGWYSSy4RwbBunrJBQ4Co8fRWA==" crossorigin="anonymous"></script>
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.8.0/leaflet.min.css" integrity="sha512-oIQ0EBio8LJupRpgmDsIsvm0Fsr6c3XNHLB7at5xb+Cf6eQuCX9xuX8XXGRIcokNgdqL1ms7nqbQ6ryXMGxXpg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.8.0/leaflet.min.js" integrity="sha512-TL+GX2RsOUlTndpkgHVnSQ9r6zldqHzfyECrdabkpucdFroZ3/HAhMmP2WYaPjsJCoot+0McmdPOLjmmicG9qg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-plugins/3.4.0/control/Permalink.min.js" integrity="sha512-wEr+4N2qhQn/6/YACFWVAaKzS2vLeZCWyUJ14MfXGTfHG718QBvOqv9t5xhex+Fnd3VZVd0EWcn9nzRbTLL9bg==" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-plugins/3.4.0/control/Permalink.Layer.min.js" integrity="sha512-m7ds5hujMwIiJ9yPLnJDR4C3bFeURlrFeHnW+QpsDweqYs8hu0/cYdJFBYtRkWGFpvmF6HkOWSGy7vYP1Rg+BA==" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-plugins/3.4.0/control/Permalink.Overlay.min.js" integrity="sha512-dIzyCLt0Sg0QpDfLXJZfgwmkbjl5s+ND7uFGW6A7itxuKA241Fzp6fKmCnPLhadqqmjz5i9/1W6aCFPLNSIIXA==" crossorigin="anonymous"></script>
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha512-SfTiTlX6kk+qitfevl/7LibUOeJWlt9rbyDn92a1DqWOw9vWG2MFoays0sgObmWazO5BQPiFucnnEAjpAB+/Sw==" crossorigin="anonymous" />
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet-locatecontrol/0.73.0/L.Control.Locate.min.css" integrity="sha512-61KpOy3DnpOq3pZlp54eyUdvq9ub53e2ETbksuRlQCMNiAkqyB2Iz8a6ggg61e9zlvPImPz+7A0tgvNGaoVLZg==" crossorigin="anonymous" />
- <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-locatecontrol/0.73.0/L.Control.Locate.min.js" integrity="sha512-taGzWgtN8FsSonl7SSrfPQBvTm/omZEf9p0s64IomW39xQZx8bSmP+aUyzeqig61ojVlMUwW5Moyo87HNQxliw==" crossorigin="anonymous"></script>
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet.locatecontrol@0.76.1/dist/L.Control.Locate.min.css" integrity="sha256-9ouZwdHZxE1t+iXfxZD90z8xHQrynHnPJk1UgEPXolI=" crossorigin="anonymous" referrerpolicy="no-referrer" />
+ <script src="https://cdn.jsdelivr.net/npm/leaflet.locatecontrol@0.76.1/dist/L.Control.Locate.min.js" charset="utf-8" integrity="sha256-PJ29AcM0ZkANjcOdpF1jAwZ/eq324NP2cQ05f2wABE0=" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script type="text/javascript" src="imagery.js"></script>
<style type="text/css">
<% end -%>
IMAGETYPE <%= @extension %>
PROJECTION
- <% if @projection == "EPSG:27700" -%>
- <%# Override EPSG:27700 to use accurate nadgrid %>
- "+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +datum=OSGB36 +units=m +no_defs +nadgrids=/srv/imagery/common/ostn02-ntv2-data/OSTN02_NTv2.gsb"
- <% elsif @projection == "namibia_aerial" -%>
+ <% if @projection == "namibia_aerial" -%>
"+proj=tmerc +lat_0=0 +lon_0=17 +k=1 +x_0=600000 +y_0=10000000 +ellps=WGS84 +units=m +no_defs"
<% else -%>
"init=<%= @projection.downcase %>"
NAME "<%= @layer %>"
DATA "<%= @source %>"
PROJECTION
- <% if @projection == "EPSG:27700" -%>
- <%# Override EPSG:27700 to use accurate nadgrid %>
- "+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +datum=OSGB36 +units=m +no_defs +nadgrids=/srv/imagery/common/ostn02-ntv2-data/OSTN02_NTv2.gsb"
- <% elsif @projection == "namibia_aerial" -%>
+ <% if @projection == "namibia_aerial" -%>
"+proj=tmerc +lat_0=0 +lon_0=17 +k=1 +x_0=600000 +y_0=10000000 +ellps=WGS84 +units=m +no_defs"
<% else -%>
"init=<%= @projection.downcase %>"
server {
listen 80 deferred backlog=16384 reuseport default_server;
listen 443 ssl deferred backlog=16384 reuseport http2; # No default_server here unless certificate specified here too.
+ listen [::]:80 deferred backlog=16384 reuseport default_server;
+ listen [::]:443 ssl deferred backlog=16384 reuseport http2; # No default_server here unless certificate specified here too.
server_name _;
default_type text/html;
server {
listen 80;
+ listen [::]:80;
server_name <%= @name %> a.<%= @name %> b.<%= @name %> c.<%= @name %><% @aliases.each do |alias_name| %> <%= alias_name %> a.<%= alias_name %> b.<%= alias_name %> c.<%= alias_name %><%- end -%>;
rewrite ^/\.well-known/acme-challenge/(.*)$ http://acme.openstreetmap.org/.well-known/acme-challenge/$1 permanent;
return 301 https://$host$request_uri;
}
+<% if @uses_tiler -%>
+upstream tiler_backend {
+ server 127.0.0.1:8080 max_fails=0;
+
+ keepalive 32;
+}
+<% else -%>
upstream <%= @name %>_fastcgi {
- server "unix:/var/run/mapserver-fastcgi/layer-<%= @name %>-0.socket" max_fails=0;
- server "unix:/var/run/mapserver-fastcgi/layer-<%= @name %>-1.socket" max_fails=0;
- server "unix:/var/run/mapserver-fastcgi/layer-<%= @name %>-2.socket" max_fails=0;
- server "unix:/var/run/mapserver-fastcgi/layer-<%= @name %>-3.socket" max_fails=0;
- server "unix:/var/run/mapserver-fastcgi/layer-<%= @name %>-4.socket" max_fails=0;
- server "unix:/var/run/mapserver-fastcgi/layer-<%= @name %>-5.socket" max_fails=0;
- server "unix:/var/run/mapserver-fastcgi/layer-<%= @name %>-6.socket" max_fails=0;
- server "unix:/var/run/mapserver-fastcgi/layer-<%= @name %>-7.socket" max_fails=0;
+ server "unix:/var/run/mapserver-fastcgi/layer-<%= @name %>.socket" max_fails=0;
# Use default round-robin to distribute requests, rather than pick "fast" but maybe faulty.
# Do not use keepalive
}
+<% end -%>
server {
listen 443 ssl http2;
+ listen [::]:443 ssl http2;
server_name <%= @name %> a.<%= @name %> b.<%= @name %> c.<%= @name %><% @aliases.each do |alias_name| %> <%= alias_name %> a.<%= alias_name %> b.<%= alias_name %> c.<%= alias_name %><%- end -%>;
+ http2_max_concurrent_streams 512;
+ keepalive_timeout 30s;
+
ssl_certificate /etc/ssl/certs/<%= @name %>.pem;
ssl_certificate_key /etc/ssl/private/<%= @name %>.key;
<% if node[:ssl][:strict_transport_security] -%>
+<% require 'uri' %>
# DO NOT EDIT - This file is being maintained by Chef
location ~* "^/layer/<%= @layer %>/(\d+)/(\d+)/(\d+)\.(png|jpg|jpeg)$" {
+<% if @uses_tiler -%>
+ set $args "";
+ rewrite ^/layer/<%= @layer %>/(\d+)/(\d+)/(\d+)\.jpg /mosaicjson/tiles/WebMercatorQuad/$1/$2/$3@1x?url=<%= URI.encode_www_form_component(@source) %>&pixel_selection=first&tile_format=jpeg break;
+ rewrite ^/layer/<%= @layer %>/(\d+)/(\d+)/(\d+)\.jpeg /mosaicjson/tiles/WebMercatorQuad/$1/$2/$3@1x?url=<%= URI.encode_www_form_component(@source) %>&pixel_selection=first&tile_format=jpeg break;
+ rewrite ^/layer/<%= @layer %>/(\d+)/(\d+)/(\d+)\.png /mosaicjson/tiles/WebMercatorQuad/$1/$2/$3@1x?url=<%= URI.encode_www_form_component(@source) %>&pixel_selection=first&tile_format=png break;
+ proxy_pass http://tiler_backend;
+ proxy_set_header Host $host;
+ proxy_set_header Referer $http_referer;
+ proxy_set_header X-Forwarded-For $remote_addr;
+ proxy_set_header X-Forwarded-Proto https;
+ proxy_set_header X-Forwarded-SSL on;
+ proxy_http_version 1.1;
+ proxy_set_header Connection "";
+ proxy_set_header Cache-Control "";
+ proxy_set_header Pragma "";
+ proxy_redirect off;
+ proxy_cache_key "<%= @layer %><%= @revision %> $request_method $1 $2 $3";
+ proxy_cache proxy_cache_zone;
+ proxy_cache_valid 200 204 180d;
+ proxy_cache_use_stale error timeout updating http_502 http_503 http_504;
+ proxy_cache_background_update on;
+ proxy_next_upstream error timeout invalid_header http_500 http_503;
+ proxy_next_upstream_tries 3;
+ proxy_next_upstream_timeout 30s;
+
+<% else -%>
# Override QUERY_STRING to force mapserver query parameters
fastcgi_param QUERY_STRING "map=/srv/imagery/mapserver/layer-<%= @layer %>.map&mode=tile&layers=<%= @layer %>&tilemode=gmap&tile=$2+$3+$1";
fastcgi_pass "<%= @site %>_fastcgi";
- fastcgi_buffers 8 64k;
- fastcgi_busy_buffers_size 64k;
include fastcgi_params;
fastcgi_param REQUEST_METHOD "GET";
fastcgi_param HTTP_PROXY "";
keepalive_requests 0;
- # Ignore client abort as it causes issues with the pipeline
- fastcgi_ignore_client_abort on;
-
fastcgi_catch_stderr "Image handling error";
fastcgi_next_upstream error timeout invalid_header http_500 http_503;
fastcgi_next_upstream_tries 8;
+<% end -%>
# Do not GZIP tiles
gzip off;
--- /dev/null
+server {
+ listen 80;
+ listen [::]:80;
+ server_name <%= @name %> <% @aliases.each do |alias_name| %> <%= alias_name %><%- end -%>;
+
+ rewrite ^/\.well-known/acme-challenge/(.*)$ http://acme.openstreetmap.org/.well-known/acme-challenge/$1 permanent;
+
+ location / {
+ return 301 https://$host$request_uri;
+ }
+
+ location /za-25cm {
+ root "/store/imagery/za";
+ expires max;
+ }
+}
+
+server {
+ listen 443 ssl http2;
+ listen [::]:443 ssl http2;
+ server_name <%= @name %> <% @aliases.each do |alias_name| %> <%= alias_name %><%- end -%>;
+
+ http2_max_concurrent_streams 512;
+ keepalive_timeout 30s;
+
+ ssl_certificate /etc/ssl/certs/<%= @name %>.pem;
+ ssl_certificate_key /etc/ssl/private/<%= @name %>.key;
+<% if node[:ssl][:strict_transport_security] -%>
+
+ add_header Strict-Transport-Security "<%= node[:ssl][:strict_transport_security] %>" always;
+<% end -%>
+
+ # Requests sent within early data are subject to replay attacks.
+ # See: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_early_data
+ ssl_early_data on;
+
+ # root "/srv/<%= @name %>";
+
+ gzip on;
+ gzip_types text/plain text/css application/json application/javascript application/x-javascript text/javascript text/xml application/xml application/rss+xml application/atom+xml application/rdf+xml image/svg+xml; # text/html is implicit
+ gzip_min_length 512;
+ gzip_http_version 1.0;
+ gzip_proxied any;
+ gzip_comp_level 9;
+ gzip_vary on;
+
+ location /za-25cm {
+ root "/store/imagery/za";
+ expires max;
+ }
+
+ location /api/v1/titiler {
+ rewrite ^/api/v1/titiler(.*)$ $1 break;
+ proxy_pass http://localhost:8080;
+ proxy_set_header Host $host;
+ proxy_set_header Referer $http_referer;
+ proxy_set_header X-Forwarded-For $remote_addr;
+ proxy_set_header X-Forwarded-Proto https;
+ proxy_set_header X-Forwarded-SSL on;
+ proxy_http_version 1.1;
+ proxy_set_header Connection "";
+ proxy_redirect off;
+ }
+}
+++ /dev/null
-# incron Cookbook
-
-This cookbook installs incron, an inotify-based cron.
+++ /dev/null
-default[:incron] = {}
+++ /dev/null
-#
-# Cookbook:: incron
-# Recipe:: default
-#
-# Copyright:: 2014, OpenStreetMap Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-package "incron"
-
-service "incron" do
- action [:enable, :start]
- supports :status => true, :reload => true, :restart => true
-end
-
-incrontabs = {}
-
-node[:incron].each_value do |details|
- user = details[:user]
- path = details[:path]
- mask = details[:events].join(",")
- command = details[:command]
-
- incrontabs[user] ||= []
-
- incrontabs[user].push("#{path} #{mask} #{command}")
-end
-
-incrontabs.each do |user, lines|
- file "/var/spool/incron/#{user}" do
- owner user
- group "incron"
- mode "600"
- content lines.join("\n")
- end
-end
-
-file "/etc/incron.allow" do
- owner "root"
- group "incron"
- mode "0640"
- content incrontabs.keys.sort.join("\n")
-end
+++ /dev/null
-<!DOCTYPE html>
-<html>
- <head>
- <title>irc.openstreetmap.org</title>
- <link rel="stylesheet" href="style.css" />
- </head>
- <body>
- <h1>irc.openstreetmap.org</h1>
- <div>
- <form method="get" action="https://webchat.oftc.net/">
- <table>
- <tr>
- <th>Nickname</th>
- <td><input name="nick" type="text" /></td>
- </tr>
- <tr>
- <th>Channel</th>
- <td>
- <select name="channels">
- <option value="#osm">#osm</option>
- <option value="#osm-dev">#osm-dev</option>
- <option value="#osm-ewg">#osm-ewg</option>
- <option value="#osm-cwg">#osm-cwg</option>
- <option value="#osm-ar">#osm-ar</option>
- <option value="#osm-asia">#osm-asia</option>
- <option value="#osm-au">#osm-au</option>
- <option value="#osm-br">#osm-br</option>
- <option value="#osm-bw">#osm-bw</option>
- <option value="#osm-by">#osm-by</option>
- <option value="#osm-ca">#osm-ca</option>
- <option value="#osm-ch">#osm-ch</option>
- <option value="#osm-cz">#osm-cz</option>
- <option value="#osm-de">#osm-de</option>
- <option value="#osm-dk">#osm-dk</option>
- <option value="#osm-es">#osm-es</option>
- <option value="#osm-fi">#osm-fi</option>
- <option value="#osm-fr">#osm-fr</option>
- <option value="#osm-gb">#osm-gb</option>
- <option value="#osm-gr">#osm-gr</option>
- <option value="#osm-gsoc">#osm-gsoc</option>
- <option value="#osm-ht">#osm-ht</option>
- <option value="#osm-ie">#osm-ie</option>
- <option value="#osm-it">#osm-it</option>
- <option value="#osm-ke">#osm-ke</option>
- <option value="#osm-latam">#osm-latam</option>
- <option value="#osm-local">#osm-local</option>
- <option value="#osm-lv">#osm-lv</option>
- <option value="#osm-nl">#osm-nl</option>
- <option value="#osm-no">#osm-no</option>
- <option value="#osm-nominatim">#osm-nominatim</option>
- <option value="#osm-pl">#osm-pl</option>
- <option value="#osm-pt">#osm-pt</option>
- <option value="#osm-ru">#osm-ru</option>
- <option value="#osm.se">#osm.se</option>
- <option value="#osm-strategic">#osm-strategic</option>
- <option value="#osm-ua">#osm-ua</option>
- <option value="#osm-us">#osm-us</option>
- <option value="#osm-za">#osm-za</option>
- <option value="#osm-zh">#osm-zh</option>
- <option value="#osmf-gm">#osmf-gm</option>
- <option value="#osrm">#osrm</option>
- <option value="#openrailwaymap">#openrailwaymap</option>
- <option value="#hot">#hot</option>
- </select>
- </td>
- </tr>
- <tr>
- <th></th>
- <td><input type="submit" value="Connect" /></td>
- </tr>
- </table>
- </form>
- </div>
- </body>
-</html>
+++ /dev/null
-h1 {
- text-align: center;
-}
-
-div {
- display: flex;
-}
-
-form {
- margin: auto;
-}
version "1.0.0"
supports "ubuntu"
-depends "apache"
+depends "podman"
# limitations under the License.
#
-include_recipe "apache"
+include_recipe "podman::apache"
-ssl_certificate "irc.openstreetmap.org" do
- domains ["irc.openstreetmap.org", "irc.osm.org"]
- notifies :reload, "service[apache2]"
-end
-
-directory "/srv/irc.openstreetmap.org" do
- owner "root"
- group "root"
- mode "755"
-end
-
-remote_directory "/srv/irc.openstreetmap.org/html" do
- source "html"
- owner "root"
- group "root"
- mode "755"
- files_owner "root"
- files_group "root"
- files_mode "644"
-end
-
-apache_site "irc.openstreetmap.org" do
- template "apache.erb"
- directory "/srv/irc.openstreetmap.org/html"
- variables :aliases => ["irc.osm.org"]
+podman_site "irc.openstreetmap.org" do
+ image "ghcr.io/openstreetmap/irc-website:latest"
+ aliases ["irc.osm.org"]
end
mode "755"
end
-execute "unzip-kibana-#{version}" do
- command "tar --gunzip --extract --strip-components=1 --file=#{Chef::Config[:file_cache_path]}/kibana-#{version}.tar.gz"
- cwd "/opt/kibana-#{version}"
- user "root"
+archive_file "#{Chef::Config[:file_cache_path]}/kibana-#{version}.tar.gz" do
+ destination "/opt/kibana-#{version}"
+ overwrite true
+ strip_components 1
+ owner "root"
group "root"
not_if { ::File.exist?("/opt/kibana-#{version}/bin/kibana") }
end
ServerName <%= @site %>
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/<%= @site %>-access.log combined
+ CustomLog /var/log/apache2/<%= @site %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @site %>-error.log
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
ServerName <%= @site %>
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/<%= @site %>-access.log combined
+ CustomLog /var/log/apache2/<%= @site %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @site %>-error.log
SSLEngine on
/usr/bin/certbot renew \
--quiet \
- --preferred-chain "DST Root CA X3" \
--config-dir /srv/acme.openstreetmap.org/config \
--work-dir /srv/acme.openstreetmap.org/work \
--logs-dir /srv/acme.openstreetmap.org/logs \
#!/bin/bash
-domains=($RENEWED_DOMAINS)
-
exec 2>&1
-exec /srv/acme.openstreetmap.org/bin/upload "${domains[0]}" "$RENEWED_LINEAGE"
+exec /srv/acme.openstreetmap.org/bin/upload "$(basename $RENEWED_LINEAGE)" "$RENEWED_LINEAGE"
file.puts JSON.generate(bag)
file.close
-system("/usr/bin/knife", "data", "bag", "from", "file", "letsencrypt", file.path)
+system("/opt/chef/embedded/bin/knife", "data", "bag", "from", "file", "letsencrypt", file.path)
supports "ubuntu"
depends "accounts"
depends "apache"
+depends "chef"
include_recipe "accounts"
include_recipe "apache"
+include_recipe "chef::knife"
keys = data_bag_item("chef", "keys")
user "letsencrypt"
group "letsencrypt"
subscribes :run, "template[/srv/acme.openstreetmap.org/requests/#{name}]"
- not_if { ENV["TEST_KITCHEN"] }
+ not_if { kitchen? }
end
end
variables :certificates => certificates
end
-cron_d "letencrypt-renew" do
- minute "00"
- hour "*/12"
+systemd_service "letsencrypt-renew" do
+ description "Renew letsencrypt certificates"
+ exec_start "/srv/acme.openstreetmap.org/bin/renew"
user "letsencrypt"
- command "/srv/acme.openstreetmap.org/bin/renew"
- mailto "admins@openstreetmap.org"
+ sandbox :enable_network => true
+ read_write_paths [
+ "/srv/acme.openstreetmap.org/config",
+ "/srv/acme.openstreetmap.org/html",
+ "/srv/acme.openstreetmap.org/logs",
+ "/srv/acme.openstreetmap.org/work"
+ ]
end
-cron_d "letencrypt-check" do
- minute "30"
- hour "*/12"
+systemd_timer "letsencrypt-renew" do
+ description "Renew letsencrypt certificates"
+ on_boot_sec "1h"
+ on_unit_inactive_sec "12h"
+end
+
+service "letsencrypt-renew.timer" do
+ action [:enable, :start]
+end
+
+systemd_service "letsencrypt-check" do
+ description "Check letsencrypt certificates"
+ exec_start "/srv/acme.openstreetmap.org/bin/check-certificates"
user "letsencrypt"
- command "/srv/acme.openstreetmap.org/bin/check-certificates"
- mailto "admins@openstreetmap.org"
+ sandbox :enable_network => true
+end
+
+systemd_timer "letsencrypt-check" do
+ description "Check letsencrypt certificates"
+ on_boot_sec "2h"
+ on_unit_inactive_sec "12h"
+end
+
+service "letsencrypt-check.timer" do
+ action [:enable, :start]
end
template "/etc/logrotate.d/letsencrypt" do
ServerAlias acme.osm.org
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/acme.openstreetmap.org-access.log combined
+ CustomLog /var/log/apache2/acme.openstreetmap.org-access.log combined_extended
ErrorLog /var/log/apache2/acme.openstreetmap.org-error.log
DocumentRoot /srv/acme.openstreetmap.org/html
ServerAlias acme.osm.org
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/acme.openstreetmap.org-access.log combined
+ CustomLog /var/log/apache2/acme.openstreetmap.org-access.log combined_extended
ErrorLog /var/log/apache2/acme.openstreetmap.org-error.log
SSLEngine on
/usr/bin/certbot certonly \
--non-interactive \
- --preferred-chain "DST Root CA X3" \
--config-dir /srv/acme.openstreetmap.org/config \
--work-dir /srv/acme.openstreetmap.org/work \
--logs-dir /srv/acme.openstreetmap.org/logs \
default[:logstash][:forwarder]["output.logstash"]["hosts"] = ["logstash.openstreetmap.org:5044"]
default[:logstash][:forwarder]["output.logstash"]["ssl.certificate_authorities"] = "/etc/filebeat/filebeat.crt"
default[:logstash][:forwarder]["output.logstash"]["ssl.verification_mode"] = "none"
-default[:logstash][:forwarder]["filebeat.prospectors"] = []
+default[:logstash][:forwarder]["filebeat.inputs"] = []
default[:elasticsearch][:cluster][:name] = "logstash"
keys = data_bag_item("logstash", "keys")
package %w[
- openjdk-8-jre-headless
+ openjdk-11-jre-headless
logstash
]
mode "755"
end
-forwarders = search(:node, "recipes:logstash\\:\\:forwarder")
+forwarders = []
-forwarders.sort_by { |n| n[:fqdn] }.each do |forwarder|
- forwarder.interfaces(:role => :external) do |interface|
- firewall_rule "accept-lumberjack-#{forwarder}" do
- action :accept
- family interface[:family]
- source "#{interface[:zone]}:#{interface[:address]}"
- dest "fw"
- proto "tcp:syn"
- dest_ports "5043"
- source_ports "1024:"
- end
-
- firewall_rule "accept-beats-#{forwarder}" do
- action :accept
- family interface[:family]
- source "#{interface[:zone]}:#{interface[:address]}"
- dest "fw"
- proto "tcp:syn"
- dest_ports "5044"
- source_ports "1024:"
- end
- end
+search(:node, "recipes:logstash\\:\\:forwarder").each do |forwarder|
+ forwarders.append(forwarder.ipaddresses(:role => :external))
end
-gateways = search(:node, "roles:gateway")
-
-gateways.sort_by { |n| n[:fqdn] }.each do |gateway|
- gateway.interfaces(:role => :external) do |interface|
- firewall_rule "accept-lumberjack-#{gateway}" do
- action :accept
- family interface[:family]
- source "#{interface[:zone]}:#{interface[:address]}"
- dest "fw"
- proto "tcp:syn"
- dest_ports "5043"
- source_ports "1024:"
- end
+search(:node, "roles:gateway").each do |forwarder|
+ forwarders.append(forwarder.ipaddresses(:role => :external))
+end
- firewall_rule "accept-beats-#{gateway}" do
- action :accept
- family interface[:family]
- source "#{interface[:zone]}:#{interface[:address]}"
- dest "fw"
- proto "tcp:syn"
- dest_ports "5044"
- source_ports "1024:"
- end
- end
+firewall_rule "accept-logstash" do
+ action :accept
+ context :incoming
+ protocol :tcp
+ source forwarders
+ dest_ports %w[5043 5044]
+ source_ports "1024-65535"
+ not_if { forwarders.empty? }
end
require "yaml"
-include_recipe "apt"
+include_recipe "apt::elasticsearch8"
package "filebeat"
supports "ubuntu"
depends "apache"
depends "chef"
+depends "prometheus"
require "securerandom"
include_recipe "apache"
+include_recipe "prometheus"
package %w[
locales-all
mailman
+ ruby-webrick
]
subscribe_form_secret = persistent_token("mailman", "subscribe_form_secret")
group "root"
mode "755"
end
+
+prometheus_exporter "mailman" do
+ port 8083
+ user "list"
+end
<% end -%>
ServerAdmin postmaster@openstreetmap.org
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
RedirectPermanent / https://<%= @name %>/
SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
LogLevel warn
RedirectMatch ^/$ /listinfo
RedirectMatch ^/cgi-bin/mailman/(.*)$ /$1
+ # Redact list archive entries per request of talk moderators
+ RedirectMatch 451 ^/pipermail/talk/2022-July/(087645|087647)\.html$
+
<Directory /var/lib/mailman/archives/>
Options Indexes FollowSymLinks
AllowOverride None
ScriptAlias /subscribe /usr/lib/cgi-bin/mailman/subscribe
ScriptAlias /mailman/ /usr/lib/cgi-bin/mailman/
- <Location ~ "/pipermail/([^/]+)/(2004|2005|2006|2007|2008|2009|2010|2011|2012|2013|2014|2015|2016|2017|2018)">
+ <% last_year = year = Time.now.year - 1 %>
+ <Location ~ "/pipermail/([^/]+)/(<%= (2004..last_year).to_a.join('|') %>)">
ExpiresActive On
ExpiresDefault "access plus 180 days"
</Location>
export RSYNC_RSH="ssh -ax"
-nice tar --create --dereference --warning=no-file-changed --directory=$T lists-$D | nice gzip --rsyncable -9 > $T/$B
+nice tar --create --dereference --warning=no-file-changed --warning=no-file-removed --directory=$T lists-$D | nice gzip --rsyncable -9 > $T/$B
nice rsync --preallocate --fuzzy $T/$B backup::backup
rm -rf $T
--- /dev/null
+# Matomo Cookbook
+
+This cookbook installs and configures the Matomo server-side software used for
+analytics on openstreetmap.org
--- /dev/null
+default[:matomo][:version] = "5.0.1"
+default[:matomo][:plugins] = {
+ "Actions" => nil,
+ "Annotations" => nil,
+ "API" => nil,
+ "BulkTracking" => nil,
+ "Contents" => nil,
+ "CoreAdminHome" => nil,
+ "CoreConsole" => nil,
+ "CoreHome" => nil,
+ "CorePluginsAdmin" => nil,
+ "CoreUpdater" => nil,
+ "CoreVisualizations" => nil,
+ "CoreVue" => nil,
+ "CustomJsTracker" => nil,
+ "Dashboard" => nil,
+ "DBStats" => nil,
+ "DeviceFeatureWebGL" => "5.0.0",
+ "DevicePlugins" => nil,
+ "DevicesDetection" => nil,
+ "Diagnostics" => nil,
+ "Ecommerce" => nil,
+ "Events" => nil,
+ "Feedback" => nil,
+ "GeoIp2" => nil,
+ "Goals" => nil,
+ "Heartbeat" => nil,
+ "ImageGraph" => nil,
+ "Insights" => nil,
+ "Installation" => nil,
+ "Intl" => nil,
+ "IntranetMeasurable" => nil,
+ "LanguagesManager" => nil,
+ "Live" => nil,
+ "Login" => nil,
+ "Marketplace" => nil,
+ "MobileAppMeasurable" => nil,
+ "MobileMessaging" => nil,
+ "Monolog" => nil,
+ "Morpheus" => nil,
+ "MultiSites" => nil,
+ "Overlay" => nil,
+ "PagePerformance" => nil,
+ "PrivacyManager" => nil,
+ "ProfessionalServices" => nil,
+ "Proxy" => nil,
+ "Referrers" => nil,
+ "Resolution" => nil,
+ "RssWidget" => nil,
+ "ScheduledReports" => nil,
+ "SegmentEditor" => nil,
+ "SEO" => nil,
+ "SitesManager" => nil,
+ "Tour" => nil,
+ "Transitions" => nil,
+ "TwoFactorAuth" => nil,
+ "UserCountry" => nil,
+ "UserCountryMap" => nil,
+ "UserId" => nil,
+ "UserLanguage" => nil,
+ "UsersManager" => nil,
+ "VisitFrequency" => nil,
+ "VisitorInterest" => nil,
+ "VisitsSummary" => nil,
+ "VisitTime" => nil,
+ "WebsiteMeasurable" => nil,
+ "Widgetize" => nil,
+}
+
+default[:mysql][:settings][:mysqld][:secure_file_priv] = "/opt/matomo-#{node[:matomo][:version]}/matomo/tmp/assets"
-name "piwik"
+name "matomo"
maintainer "OpenStreetMap Administrators"
maintainer_email "admins@openstreetmap.org"
license "Apache-2.0"
-description "Installs and configures Piwik"
+description "Installs and configures Matomo"
version "1.0.0"
supports "ubuntu"
depends "geoipupdate"
depends "mysql"
depends "php"
+depends "systemd"
--- /dev/null
+#
+# Cookbook:: matomo
+# Recipe:: default
+#
+# Copyright:: 2011, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "apache"
+include_recipe "geoipupdate"
+include_recipe "mysql"
+include_recipe "php::fpm"
+
+passwords = data_bag_item("matomo", "passwords")
+
+package %w[
+ brotli
+ gzip
+ php-cli
+ php-curl
+ php-mbstring
+ php-mysql
+ php-gd
+ php-xml
+ php-apcu
+]
+
+apache_module "expires"
+apache_module "proxy"
+apache_module "proxy_fcgi"
+apache_module "rewrite"
+
+version = node[:matomo][:version]
+
+geoip_directory = node[:geoipupdate][:directory]
+
+remote_file "#{Chef::Config[:file_cache_path]}/matomo-#{version}.zip" do
+ source "https://builds.matomo.org/matomo-#{version}.zip"
+end
+
+archive_file "#{Chef::Config[:file_cache_path]}/matomo-#{version}.zip" do
+ destination "/opt/matomo-#{version}"
+ notifies :run, "notify_group[matomo-updated]"
+end
+
+node[:matomo][:plugins].each do |plugin_name, plugin_version|
+ next if plugin_version.nil?
+
+ remote_file "#{Chef::Config[:file_cache_path]}/matomo-#{plugin_name}-#{plugin_version}.zip" do
+ source "https://plugins.matomo.org/api/2.0/plugins/#{plugin_name}/download/#{plugin_version}"
+ end
+
+ archive_file "#{Chef::Config[:file_cache_path]}/matomo-#{plugin_name}-#{plugin_version}.zip" do
+ destination "/opt/matomo-#{plugin_name}-#{plugin_version}"
+ end
+
+ link "/opt/matomo-#{version}/matomo/plugins/#{plugin_name}" do
+ to "/opt/matomo-#{plugin_name}-#{plugin_version}/#{plugin_name}"
+ notifies :run, "notify_group[matomo-updated]"
+ end
+end
+
+directory "/opt/matomo-#{version}/matomo/config" do
+ owner "www-data"
+ group "www-data"
+ mode "0755"
+end
+
+template "/opt/matomo-#{version}/matomo/config/config.ini.php" do
+ source "config.erb"
+ owner "root"
+ group "root"
+ mode "0644"
+ variables :passwords => passwords,
+ :directory => "/opt/matomo-#{version}/matomo",
+ :plugins => node[:matomo][:plugins].keys.sort
+ notifies :run, "notify_group[matomo-updated]"
+end
+
+directory "/opt/matomo-#{version}/matomo/tmp" do
+ owner "www-data"
+ group "www-data"
+ mode "0755"
+end
+
+directory "/opt/matomo-#{version}/matomo/tmp/assets" do
+ owner "www-data"
+ group "mysql"
+ mode "0750"
+end
+
+directory "/opt/matomo-#{version}/matomo/tmp/cache" do
+ owner "www-data"
+ group "www-data"
+ mode "0750"
+end
+
+link "/opt/matomo-#{version}/matomo/misc/GeoLite2-ASN.mmdb" do
+ to "#{geoip_directory}/GeoLite2-ASN.mmdb"
+end
+
+link "/opt/matomo-#{version}/matomo/misc/GeoLite2-City.mmdb" do
+ to "#{geoip_directory}/GeoLite2-City.mmdb"
+end
+
+link "/opt/matomo-#{version}/matomo/misc/GeoLite2-Country.mmdb" do
+ to "#{geoip_directory}/GeoLite2-Country.mmdb"
+end
+
+mysql_user "piwik@localhost" do
+ password passwords["database"]
+end
+
+mysql_database "piwik" do
+ permissions "piwik@localhost" => :all
+end
+
+notify_group "matomo-updated"
+
+if File.symlink?("/srv/matomo.openstreetmap.org")
+ execute "core:update" do
+ action :nothing
+ command "/opt/matomo-#{version}/matomo/console core:update --yes"
+ user "www-data"
+ group "www-data"
+ subscribes :run, "notify_group[matomo-updated]"
+ end
+
+ execute "custom-matomo-js:update" do
+ action :nothing
+ command "/opt/matomo-#{version}/matomo/console custom-matomo-js:update"
+ user "root"
+ group "root"
+ subscribes :run, "execute[core:update]"
+ end
+
+ execute "/opt/matomo-#{version}/matomo/matomo.br" do
+ action :nothing
+ command "brotli --keep --force --best /opt/matomo-#{version}/matomo/matomo.js"
+ cwd "/opt/matomo-#{version}"
+ user "root"
+ group "root"
+ subscribes :run, "execute[custom-matomo-js:update]"
+ end
+
+ execute "/opt/matomo-#{version}/matomo/matomo.js" do
+ action :nothing
+ command "gzip --keep --force --best /opt/matomo-#{version}/matomo/matomo.js"
+ cwd "/opt/matomo-#{version}"
+ user "root"
+ group "root"
+ subscribes :run, "execute[custom-matomo-js:update]"
+ end
+
+ execute "/opt/matomo-#{version}/matomo/piwik.br" do
+ action :nothing
+ command "brotli --keep --force --best /opt/matomo-#{version}/matomo/piwik.js"
+ cwd "/opt/matomo-#{version}"
+ user "root"
+ group "root"
+ subscribes :run, "execute[custom-matomo-js:update]"
+ end
+
+ execute "/opt/matomo-#{version}/matomo/piwik.js" do
+ action :nothing
+ command "gzip --keep --force --best /opt/matomo-#{version}/matomo/piwik.js"
+ cwd "/opt/matomo-#{version}"
+ user "root"
+ group "root"
+ subscribes :run, "execute[custom-matomo-js:update]"
+ end
+end
+
+link "/srv/matomo.openstreetmap.org" do
+ to "/opt/matomo-#{version}/matomo"
+ notifies :restart, "service[php#{node[:php][:version]}-fpm]"
+end
+
+ssl_certificate "matomo.openstreetmap.org" do
+ domains ["matomo.openstreetmap.org", "matomo.osm.org",
+ "piwik.openstreetmap.org", "piwik.osm.org"]
+ notifies :reload, "service[apache2]"
+end
+
+php_fpm "matomo.openstreetmap.org" do
+ prometheus_port 9253
+end
+
+apache_site "matomo.openstreetmap.org" do
+ template "apache.erb"
+end
+
+systemd_service "matomo-archive" do
+ description "Matomo report archiving"
+ exec_start "/usr/bin/php /srv/matomo.openstreetmap.org/console core:archive --url=https://matomo.openstreetmap.org/"
+ user "www-data"
+ sandbox true
+ proc_subset "all"
+ memory_deny_write_execute false
+ restrict_address_families "AF_UNIX"
+ read_write_paths "/opt/matomo-#{version}/matomo/tmp"
+end
+
+systemd_timer "matomo-archive" do
+ description "Matomo report archiving"
+ on_boot_sec "30m"
+ on_unit_inactive_sec "30m"
+end
+
+service "matomo-archive.timer" do
+ action [:enable, :start]
+end
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+<VirtualHost *:443>
+ ServerName matomo.openstreetmap.org
+ ServerAdmin webmaster@openstreetmap.org
+
+ SSLEngine on
+ SSLCertificateFile /etc/ssl/certs/matomo.openstreetmap.org.pem
+ SSLCertificateKeyFile /etc/ssl/private/matomo.openstreetmap.org.key
+
+ CustomLog /var/log/apache2/matomo.openstreetmap.org-access.log combined_extended
+ ErrorLog /var/log/apache2/matomo.openstreetmap.org-error.log
+
+ Options -Indexes
+
+ DocumentRoot /srv/matomo.openstreetmap.org
+
+ Redirect 403 /core/
+ Redirect 403 /config/
+ Redirect 403 /lang/
+ Redirect 403 /tmp/
+</VirtualHost>
+
+<VirtualHost *:443>
+ ServerName matomo.osm.org
+ ServerAlias piwik.openstreetmap.org
+ ServerAlias piwik.osm.org
+ ServerAdmin webmaster@openstreetmap.org
+
+ SSLEngine on
+ SSLCertificateFile /etc/ssl/certs/matomo.openstreetmap.org.pem
+ SSLCertificateKeyFile /etc/ssl/private/matomo.openstreetmap.org.key
+
+ CustomLog /var/log/apache2/matomo.openstreetmap.org-access.log combined_extended
+ ErrorLog /var/log/apache2/matomo.openstreetmap.org-error.log
+
+ RedirectPermanent / https://matomo.openstreetmap.org/
+</VirtualHost>
+
+<VirtualHost *:80>
+ ServerName matomo.openstreetmap.org
+ ServerAlias matomo.osm.org
+ ServerAlias piwik.openstreetmap.org
+ ServerAlias piwik.osm.org
+ ServerAdmin webmaster@openstreetmap.org
+
+ CustomLog /var/log/apache2/matomo.openstreetmap.org-access.log combined_extended
+ ErrorLog /var/log/apache2/matomo.openstreetmap.org-error.log
+
+ RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
+ RedirectPermanent / https://matomo.openstreetmap.org/
+</VirtualHost>
+
+<Directory /srv/matomo.openstreetmap.org>
+ Require all granted
+
+ ExpiresActive On
+ RewriteEngine on
+
+ RewriteCond "%{HTTP:Accept-Encoding}" "br"
+ RewriteCond "%{REQUEST_FILENAME}\.br" -s
+ RewriteRule "^(.*)\.js" "$1\.js\.br" [QSA]
+
+ RewriteCond "%{HTTP:Accept-Encoding}" "gzip"
+ RewriteCond "%{REQUEST_FILENAME}\.gz" -s
+ RewriteRule "^(.*)\.js" "$1\.js\.gz" [QSA]
+
+ RewriteRule "\.js\.(br|gz)$" "-" [T=text/javascript,E=no-gzip:1,E=no-brotli:1]
+
+ <FilesMatch "\.js\.br$">
+ Header append Content-Encoding br
+ Header append Vary Accept-Encoding
+ </FilesMatch>
+
+ <FilesMatch "\.js\.gz$">
+ Header append Content-Encoding gzip
+ Header append Vary Accept-Encoding
+ </FilesMatch>
+
+ <FilesMatch "(\.js|\.js\.gz|\.js\.br)$">
+ ExpiresDefault "access plus 1 week"
+ Header set Cache-Control "max-age=604800"
+ </FilesMatch>
+
+ <FilesMatch ".+\.ph(ar|p|tml)$">
+ SetHandler "proxy:unix:/run/php/php-matomo.openstreetmap.org-fpm.sock|fcgi://127.0.0.1"
+ </FilesMatch>
+</Directory>
; <?php exit; ?> DO NOT REMOVE THIS LINE
-; file automatically generated or modified by Piwik; you can manually override the default values in global.ini.php by redefining them in this file.
+; file automatically generated or modified by Matomo; you can manually override the default values in global.ini.php by redefining them in this file.
[database]
host = "localhost"
username = "piwik"
password = "<%= @passwords['database'] %>"
dbname = "piwik"
tables_prefix = "piwik_"
-charset = "utf8"
+charset = "utf8mb4"
[General]
force_ssl = 1
force_ssl_login = 1
login_allowlist_apply_to_reporting_api_requests = "0"
proxy_client_headers[] = "HTTP_X_FORWARDED_FOR"
+trusted_hosts[] = "matomo.openstreetmap.org"
trusted_hosts[] = "piwik.openstreetmap.org"
salt = "<%= @passwords['salt'] %>"
[Tracker]
-ignore_visits_cookie_name = "piwik_ignore"
+ignore_visits_cookie_name = "matomo_ignore"
[Plugins]
<% @plugins.each do |plugin| -%>
-# Add the mediawiki APT source
-default[:apt][:sources] = node[:apt][:sources] | ["mediawiki"]
-
# Default to enabling the "wiki" role
default[:accounts][:users][:wiki][:status] = :role
depends "memcached"
depends "mysql"
depends "php"
+depends "systemd"
# Mediawiki Base Requirements
package %w[
+ php-apcu
php-cli
php-curl
php-gd
+ php-igbinary
php-intl
+ php-memcache
php-mbstring
php-mysql
php-xml
php-zip
composer
unzip
+ ffmpeg
]
# Mediawiki enhanced difference engine
# Mediawiki packages for VisualEditor support
package %w[
curl
- parsoid
]
# Mediawiki packages for SyntaxHighight support
package "python3-pygments"
-file "/etc/mediawiki/parsoid/settings.js" do
- action :delete
+link "/etc/php/#{node[:php][:version]}/fpm/conf.d/20-wikidiff2.ini" do
+ to "../../mods-available/wikidiff2.ini"
end
-template "/etc/mediawiki/parsoid/config.yaml" do
- action :nothing
- source "parsoid-config.yaml.erb"
- owner "root"
- group "root"
- mode "644"
+apache_module "proxy"
+apache_module "proxy_fcgi"
+apache_module "rewrite"
+
+systemd_service "mediawiki-sitemap@" do
+ description "Generate sitemap.xml for %i"
+ exec_start "/usr/bin/php -d memory_limit=2048M -d error_reporting=22517 /srv/%i/w/maintenance/generateSitemap.php --server=https://%i --urlpath=https://%i/ --fspath=/srv/%i --quiet --skip-redirects"
+ user node[:mediawiki][:user]
+ nice 10
+ sandbox :enable_network => true
+ memory_deny_write_execute false
+ restrict_address_families "AF_UNIX"
+ read_write_paths "/srv/%i"
end
-notify_group "parsoid-config" do
- action :run
- notifies :create, "template[/etc/mediawiki/parsoid/config.yaml]"
+systemd_timer "mediawiki-sitemap@" do
+ description "Generate sitemap.xml for %i"
+ on_calendar "00:30"
end
-service "parsoid" do
- action [:enable]
- supports :status => false, :restart => true, :reload => false
- subscribes :restart, "file[/etc/mediawiki/parsoid/settings.js]"
- subscribes :restart, "template[/etc/mediawiki/parsoid/config.yaml]"
+systemd_service "mediawiki-jobs@" do
+ description "Run mediawiki jobs for %i"
+ exec_start "/usr/bin/php -d memory_limit=2048M -d error_reporting=22517 /srv/%i/w/maintenance/runJobs.php --server=https://%i --maxtime=175 --memory-limit=2048M --procs=8"
+ user node[:mediawiki][:user]
+ nice 10
+ runtime_max_sec 3600
+ sandbox :enable_network => true
+ memory_deny_write_execute false
+ restrict_address_families "AF_UNIX"
+ read_write_paths "/srv/%i"
end
-link "/etc/php/#{node[:php][:version]}/fpm/conf.d/20-wikidiff2.ini" do
- to "../../mods-available/wikidiff2.ini"
+systemd_timer "mediawiki-jobs@" do
+ description "Run mediawiki jobs for %i"
+ on_boot_sec "3m"
+ on_unit_inactive_sec "3m"
end
-apache_module "proxy"
-apache_module "proxy_fcgi"
-apache_module "rewrite"
+systemd_service "mediawiki-email-jobs@" do
+ description "Run mediawiki email jobs for %i"
+ exec_start "/usr/bin/php -d memory_limit=2048M -d error_reporting=22517 /srv/%i/w/maintenance/runJobs.php --server=https://%i --maxtime=55 --type=enotifNotify --memory-limit=2048M --procs=4"
+ user node[:mediawiki][:user]
+ nice 10
+ runtime_max_sec 3600
+ sandbox :enable_network => true
+ memory_deny_write_execute false
+ restrict_address_families "AF_UNIX"
+ read_write_paths "/srv/%i"
+end
+
+systemd_timer "mediawiki-email-jobs@" do
+ description "Run mediawiki email jobs for %i"
+ on_boot_sec "1m"
+ on_unit_inactive_sec "1m"
+end
+
+systemd_service "mediawiki-cleanup-gs" do
+ description "Clean up imagemagick gs_* files"
+ exec_start "/usr/bin/find /tmp -maxdepth 1 -type f -user www-data -mmin +90 -name 'gs_*' -delete"
+ user node[:mediawiki][:user]
+ sandbox true
+end
+
+systemd_timer "mediawiki-cleanup-gs" do
+ description "Clean up imagemagick gs_* files"
+ on_calendar "02:10"
+end
+
+service "mediawiki-cleanup-gs.timer" do
+ action [:enable, :start]
+end
+
+systemd_service "mediawiki-cleanup-magick" do
+ description "Clean up imagemagick magick-* files"
+ exec_start "/usr/bin/find /tmp -maxdepth 1 -type f -user www-data -mmin +90 -name 'magick-*' -delete"
+ user node[:mediawiki][:user]
+ sandbox true
+end
+
+systemd_timer "mediawiki-cleanup-magick" do
+ description "Clean up imagemagick magick-* files"
+ on_calendar "02:20"
+end
+
+service "mediawiki-cleanup-magick.timer" do
+ action [:enable, :start]
+end
mode "664"
end
end
-
- execute "#{extension_directory}/composer.json" do
- action :nothing
- command "composer update --no-dev"
- cwd mediawiki_directory
- user node[:mediawiki][:user]
- group node[:mediawiki][:group]
- environment "COMPOSER_HOME" => site_directory
- only_if { ::File.exist?("#{extension_directory}/composer.json") }
- subscribes :run, "git[#{extension_directory}]"
- end
end
action :delete do
end
def after_created
- if update_site
- notifies :update, "mediawiki_site[#{site}]"
- else
- site_directory = node[:mediawiki][:sites][site][:directory]
-
- notifies :create, "template[#{site_directory}/w/LocalSettings.php]"
- notifies :run, "execute[#{site_directory}/w/maintenance/update.php]"
- end
+ notifies :update, "mediawiki_site[#{site}]" if update_site
end
property :site, :kind_of => String, :name_property => true
property :aliases, :kind_of => [String, Array]
-property :directory, :kind_of => String
-property :version, :kind_of => String, :default => "1.35"
+property :version, :kind_of => String, :default => "1.39"
property :database_name, :kind_of => String, :required => true
property :database_user, :kind_of => String, :required => [:create, :update]
property :database_password, :kind_of => String, :required => [:create, :update]
property :admin_password, :kind_of => String, :required => [:create]
property :private_accounts, :kind_of => [TrueClass, FalseClass], :default => false
property :private_site, :kind_of => [TrueClass, FalseClass], :default => false
-property :recaptcha_public_key, :kind_of => String
-property :recaptcha_private_key, :kind_of => String
+property :hcaptcha_public_key, :kind_of => String, :default => ""
+property :hcaptcha_private_key, :kind_of => String, :default => ""
property :extra_file_extensions, :kind_of => [String, Array], :default => []
property :fpm_max_children, :kind_of => Integer, :default => 5
property :fpm_start_servers, :kind_of => Integer, :default => 2
:version => new_resource.version
}
- secret_key = persistent_token("mediawiki", new_resource.site, "wgSecretKey")
-
mysql_user "#{new_resource.database_user}@localhost" do
password new_resource.database_password
+ reload true
end
mysql_database new_resource.database_name do
mediawiki_directory = "#{site_directory}/w"
- ruby_block "rename-installer-localsettings" do
- action :nothing
- block do
- ::File.rename("#{mediawiki_directory}/LocalSettings.php", "#{mediawiki_directory}/LocalSettings-install.php")
- end
- end
-
declare_resource :directory, site_directory do
owner node[:mediawiki][:user]
group node[:mediawiki][:group]
depth 1
user node[:mediawiki][:user]
group node[:mediawiki][:group]
- notifies :run, "execute[#{mediawiki_directory}/composer.json]", :immediately
- notifies :run, "execute[#{mediawiki_directory}/maintenance/install.php]", :immediately
- notifies :run, "execute[#{mediawiki_directory}/maintenance/update.php]"
end
template "#{mediawiki_directory}/composer.local.json" do
end
execute "#{mediawiki_directory}/composer.json" do
- action :nothing
command "composer update --no-dev"
cwd mediawiki_directory
user node[:mediawiki][:user]
group node[:mediawiki][:group]
environment "COMPOSER_HOME" => site_directory
+ not_if { ::File.exist?("#{mediawiki_directory}/composer.lock") }
end
execute "#{mediawiki_directory}/maintenance/install.php" do
- action :nothing
# Use metanamespace as Site Name to ensure correct set namespace
command "php maintenance/install.php --server '#{name}' --dbtype 'mysql' --dbname '#{new_resource.database_name}' --dbuser '#{new_resource.database_user}' --dbpass '#{new_resource.database_password}' --dbserver 'localhost' --scriptpath /w --pass '#{new_resource.admin_password}' '#{new_resource.metanamespace}' '#{new_resource.admin_user}'"
cwd mediawiki_directory
user node[:mediawiki][:user]
group node[:mediawiki][:group]
- not_if do
- ::File.exist?("#{mediawiki_directory}/LocalSettings-install.php")
- end
- notifies :run, "ruby_block[rename-installer-localsettings]", :immediately
- end
-
- execute "#{mediawiki_directory}/maintenance/update.php" do
- action :nothing
- command "php maintenance/update.php --quick"
- cwd mediawiki_directory
- user node[:mediawiki][:user]
- group node[:mediawiki][:group]
- end
-
- # Safety catch if git doesn't update but install.php hasn't run
- ruby_block "catch-installer-localsettings-run" do
- action :run
- block do
- end
- not_if do
- ::File.exist?("#{mediawiki_directory}/LocalSettings-install.php")
- end
- notifies :run, "execute[#{mediawiki_directory}/maintenance/install.php]", :immediately
+ not_if { ::File.exist?("#{mediawiki_directory}/LocalSettings.php") }
end
declare_resource :directory, "#{mediawiki_directory}/images" do
:database_params => database_params,
:mediawiki => mediawiki_params,
:secret_key => secret_key
- notifies :run, "execute[#{mediawiki_directory}/maintenance/update.php]"
- end
-
- cron_d "mediawiki-#{cron_name}-sitemap" do
- comment "Generate sitemap.xml daily"
- minute "30"
- hour "0"
- user node[:mediawiki][:user]
- command "/usr/bin/nice /usr/bin/php -d memory_limit=2048M -d error_reporting=22517 #{site_directory}/w/maintenance/generateSitemap.php --server=https://#{new_resource.site} --urlpath=https://#{new_resource.site}/ --fspath=#{site_directory} --quiet --skip-redirects"
- end
-
- cron_d "mediawiki-#{cron_name}-jobs" do
- comment "Run mediawiki jobs"
- minute "*/3"
- user node[:mediawiki][:user]
- command "/usr/bin/nice /usr/bin/php -d memory_limit=2048M -d error_reporting=22517 #{site_directory}/w/maintenance/runJobs.php --server=https://#{new_resource.site} --maxtime=160 --memory-limit=2048M --procs=8 --quiet"
end
- cron_d "mediawiki-#{cron_name}-email-jobs" do
- comment "Run mediawiki email jobs"
- user node[:mediawiki][:user]
- command "/usr/bin/nice /usr/bin/php -d memory_limit=2048M -d error_reporting=22517 #{site_directory}/w/maintenance/runJobs.php --server=https://#{new_resource.site} --maxtime=30 --type=enotifNotify --memory-limit=2048M --procs=4 --quiet"
+ service "mediawiki-sitemap@#{new_resource.site}.timer" do
+ action [:enable, :start]
+ only_if { ::File.exist?("#{mediawiki_directory}/LocalSettings.php") }
end
- cron_d "mediawiki-#{cron_name}-refresh-links" do
- comment "Run mediawiki refresh links table weekly"
- minute "5"
- hour "0"
- weekday "0"
- user node[:mediawiki][:user]
- command "/usr/bin/nice /usr/bin/php -d memory_limit=2048M -d error_reporting=22517 #{site_directory}/w/maintenance/refreshLinks.php --server=https://#{new_resource.site} --memory-limit=2048M --quiet"
+ service "mediawiki-jobs@#{new_resource.site}.timer" do
+ action [:enable, :start]
+ only_if { ::File.exist?("#{mediawiki_directory}/LocalSettings.php") }
end
- cron_d "mediawiki-#{cron_name}-cleanup-gs" do
- comment "Clean up imagemagick garbage"
- minute "10"
- hour "2"
- user node[:mediawiki][:user]
- command "/usr/bin/find /tmp/ -maxdepth 1 -type f -user www-data -mmin +90 -name 'gs_*' -delete"
- end
-
- cron_d "mediawiki-#{cron_name}-cleanup-magick" do
- comment "Clean up imagemagick garbage"
- minute "20"
- hour "2"
- user node[:mediawiki][:user]
- command "/usr/bin/find /tmp/ -maxdepth 1 -type f -user www-data -mmin +90 -name 'magick-*' -delete"
+ service "mediawiki-email-jobs@#{new_resource.site}.timer" do
+ action [:enable, :start]
+ only_if { ::File.exist?("#{mediawiki_directory}/LocalSettings.php") }
end
template "/etc/cron.daily/mediawiki-#{cron_name}-backup" do
variables :name => new_resource.site,
:directory => site_directory,
:database_params => database_params
+ only_if { ::File.exist?("#{mediawiki_directory}/LocalSettings.php") }
end
# MobileFrontend extension is required by MinervaNeue skin
mediawiki_extension "MobileFrontend" do
site new_resource.site
template "mw-ext-MobileFrontend.inc.php.erb"
+ update_site false
end
# MobileFrontend extension is required by MinervaNeue skin
mediawiki_extension "ConfirmEdit" do
site new_resource.site
template "mw-ext-ConfirmEdit.inc.php.erb"
- variables :public_key => new_resource.recaptcha_public_key,
- :private_key => new_resource.recaptcha_private_key
+ variables :public_key => new_resource.hcaptcha_public_key,
+ :private_key => new_resource.hcaptcha_private_key
update_site false
end
end
update_site false
end
+ mediawiki_extension "CategoryTree" do
+ site new_resource.site
+ update_site false
+ end
+
mediawiki_extension "cldr" do
site new_resource.site
template "mw-ext-cldr.inc.php.erb"
update_site false
end
+ # Extension has been archived: https://www.mediawiki.org/wiki/Extension:LocalisationUpdate
mediawiki_extension "LocalisationUpdate" do
site new_resource.site
- template "mw-ext-LocalisationUpdate.inc.php.erb"
- update_site false
+ action :delete
end
# mediawiki_extension "Translate" do
mediawiki_extension "osmtaginfo" do
site new_resource.site
- template "mw-ext-osmtaginfo.inc.php.erb"
- repository "https://github.com/Firefishy/osmtaginfo.git"
+ repository "https://github.com/openstreetmap/osmtaginfo.git"
tag "live"
update_site false
end
update_site false
end
- mediawiki_extension "SimpleMap" do
- site new_resource.site
- template "mw-ext-SimpleMap.inc.php.erb"
- repository "https://github.com/Firefishy/SimpleMap.git"
- tag "live"
- update_site false
- action :delete
- end
-
- mediawiki_extension "SlippyMap" do
- site new_resource.site
- update_site false
- action :delete
- end
-
- mediawiki_extension "Mantle" do
- site new_resource.site
- update_site false
- action :delete
- end
-
mediawiki_extension "DisableAccount" do
site new_resource.site
template "mw-ext-DisableAccount.inc.php.erb"
mediawiki_extension "VisualEditor" do
site new_resource.site
template "mw-ext-VisualEditor.inc.php.erb"
+ variables :version => new_resource.version
update_site false
end
update_site false
end
+ if new_resource.commons
+ mediawiki_extension "QuickInstantCommons" do
+ site new_resource.site
+ update_site false
+ end
+ else
+ mediawiki_extension "QuickInstantCommons" do
+ site new_resource.site
+ update_site false
+ action :delete
+ end
+ end
+
cookbook_file "#{site_directory}/cc-wiki.png" do
cookbook "mediawiki"
owner node[:mediawiki][:user]
action :update do
mediawiki_directory = "#{site_directory}/w"
+ execute "#{mediawiki_directory}/composer.json" do
+ command "composer update --no-dev"
+ cwd mediawiki_directory
+ user node[:mediawiki][:user]
+ group node[:mediawiki][:group]
+ environment "COMPOSER_HOME" => site_directory
+ end
+
template "#{mediawiki_directory}/LocalSettings.php" do
cookbook "mediawiki"
source "LocalSettings.php.erb"
variables :name => new_resource.site,
:directory => mediawiki_directory,
:database_params => database_params,
- :mediawiki => mediawiki_params
- notifies :run, "execute[#{mediawiki_directory}/maintenance/update.php]"
+ :mediawiki => mediawiki_params,
+ :secret_key => secret_key
end
execute "#{mediawiki_directory}/maintenance/update.php" do
cwd mediawiki_directory
user node[:mediawiki][:user]
group node[:mediawiki][:group]
+ timeout 86400
end
end
end
action_class do
- include Chef::Mixin::PersistentToken
+ include OpenStreetMap::Mixin::PersistentToken
def site_directory
- new_resource.directory || "/srv/#{new_resource.site}"
+ "/srv/#{new_resource.site}"
end
def mediawiki_reference
:private_site => new_resource.private_site
}
end
+
+ def secret_key
+ persistent_token("mediawiki", new_resource.site, "wgSecretKey")
+ end
end
def after_created
+ notifies :update, "mediawiki_site[#{site}]"
notifies :reload, "service[apache2]" if reload_apache
end
end
def after_created
- if update_site
- notifies :update, "mediawiki_site[#{site}]"
- else
- site_directory = node[:mediawiki][:sites][site][:directory]
-
- notifies :create, "template[#{site_directory}/w/LocalSettings.php]"
- notifies :run, "execute[#{site_directory}/w/maintenance/update.php]"
- end
+ notifies :update, "mediawiki_site[#{site}]" if update_site
end
$wgEnotifUseJobQ = true;
+$wgSMTP = [
+ "host" => "localhost",
+ "socket_options" => [
+ "ssl" => [
+ "verify_peer_name" => false
+ ]
+ ]
+];
+
## Database settings
$wgDBtype = "mysql";
$wgDBserver = "<%= @database_params[:host] %>";
## Shared memory settings
$wgMainCacheType = CACHE_MEMCACHED;
+$wgParserCacheType = CACHE_MEMCACHED;
+$wgMessageCacheType = CACHE_MEMCACHED;
+$wgSessionCacheType = CACHE_MEMCACHED;
$wgMemCachedServers = array('127.0.0.1:11211');
$wgSessionsInObjectCache = TRUE;
$wgFileExtensions[] = 'ods';
$wgFileExtensions[] = 'svg';
$wgFileExtensions[] = 'osm';
+$wgFileExtensions[] = 'odg';
<% @mediawiki[:extra_file_extensions].each do |mw_extra_file_extension| -%>
$wgFileExtensions[] = '<%= mw_extra_file_extension %>';
<% end -%>
$wgSVGConverter = 'rsvg';
$wgSVGMaxSize = 2000;
-# InstantCommons allows wiki to use images from https://commons.wikimedia.org
-<% if @mediawiki[:commons] -%>
-$wgUseInstantCommons = true;
-<% else -%>
-$wgUseInstantCommons = false;
-<% end -%>
-
## If you use ImageMagick (or any other shell command) on a
## Linux server, this will need to be set to the name of an
## available UTF-8 locale
## Set $wgCacheDirectory to a writable directory on the web server
## to make your wiki go slightly faster. The directory should not
## be publically accessible from the web.
-#$wgCacheDirectory = "$IP/cache";
+$wgCacheDirectory = "$IP/cache";
# Site language code, should be one of the list in ./languages/Names.php
$wgLanguageCode = "en";
# Only Allow Signed-in users to edit
$wgGroupPermissions['*']['edit'] = false;
-# Only allow autoconfirmed for a few actions
-$wgGroupPermissions['user']['move'] = false;
-$wgGroupPermissions['user']['movefile'] = false;
-$wgGroupPermissions['user']['move-categorypages'] = false;
-$wgGroupPermissions['user']['upload'] = false;
-$wgGroupPermissions['autoconfirmed']['move'] = true;
-$wgGroupPermissions['autoconfirmed']['movefile'] = true;
-$wgGroupPermissions['autoconfirmed']['move-categorypages'] = true;
-$wgGroupPermissions['autoconfirmed']['upload'] = true;
-
# Allow bureaucrat group access to oversight options
$wgGroupPermissions['bureaucrat']['hideuser'] = true;
$wgGroupPermissions['bureaucrat']['deletelogentry'] = true;
$wgGroupPermissions['*']['createaccount'] = false;
$wgGroupPermissions['user']['createaccount'] = true;
<% end -%>
-<% if @mediawiki[:private_site] -%>
+<% if @mediawiki[:private_site] -%>
# Disable reading by anonymous users
$wgGroupPermissions['*']['read'] = false;
$wgUploadPath = "$wgScriptPath/img_auth.php";
<% end -%>
-<% if not(@mediawiki[:private_accounts]) and not(@mediawiki[:private_site]) -%>
-# user group "confirmed" with identical rights as "autoconfirmed", but assigned manually by sysops
-$wgGroupPermissions['confirmed'] = $wgGroupPermissions['autoconfirmed'];
-$wgAddGroups['sysop'][] = 'confirmed';
-$wgRemoveGroups['sysop'][] = 'confirmed';
-<% end -%>
-
# Allow Subpages on Main Namespace
$wgNamespacesWithSubpages[NS_MAIN] = true;
# DNS Blacklists to use
$wgEnableDnsBlacklist = true;
-$wgDnsBlacklistUrls = array( 'proxies.dnsbl.sorbs.net.', 'opm.tornevall.org.', 'xbl.spamhaus.org.', 'dnsbl-2.uceprotect.net.' );
+$wgDnsBlacklistUrls = [
+ 'proxies.dnsbl.sorbs.net.',
+ 'opm.tornevall.org.',
+ 'xbl.spamhaus.org.',
+ 'dnsbl-2.uceprotect.net.'
+];
# Require validated email to edit
$wgEmailConfirmToEdit = true;
# Extend autoblock period
$wgAutoblockExpiry = 7776000; // 90 days
-# Spam filter regex
-$wgSpamRegex = '/\b(gmail|dell|asus|eps(o|0)n|br(o|0)ther|can(o|0)n|hp|k(o|0)dak|lexmark|mcafee|bitdefender|n(o|0)rt(o|0)n( 360)?|avira|kaspersky|avg|avast|micr(o|0)s(o|0)ft|(o|0)utl(o|0)(o|0)k|printer|netgear( r(o|0)uter)?|quickb(o|0)(o|0)ks( payr(o|0)ll)?)( antivirus)?( helpline| cust(o|0)mer|( technical| tech)| cust(o|0)mer service)? (supp(o|0)rt number|ph(o|0)ne number|supp(o|0)rt ph(o|0)ne number|care number|helpdesk number)\b/i';
-
-# Autopromote users to autoconfirmed
-$wgAutoConfirmAge = 345600; // 4 days
-$wgAutoConfirmCount = 10;
-
# Disable Hit Counter for Performance
$wgDisableCounters = TRUE;
# Disable IP in Header to avoid cache issue
$wgShowIPinHeader = FALSE;
-# Job Runs mostly by cron
-$wgJobRunRate = 0.01;
+# Job Runs by cron
+$wgJobRunRate = 0;
# dissolves double redirects automatically
$wgFixDoubleRedirects = TRUE;
# Allow external images from a few sites
-$wgAllowExternalImagesFrom = array( 'http://tile.openstreetmap.org/', 'https://tile.openstreetmap.org', 'http://josm.openstreetmap.de/', 'http://trac.openstreetmap.org/', 'http://rweait.dev.openstreetmap.org/' );
-
-$wgNoFollowDomainExceptions = array( 'www.openstreetmap.org', 'josm.openstreetmap.de', 'taginfo.openstreetmap.org', 'blog.openstreetmap.org', 'wiki.osmfoundation.org' );
-
-# FIXME - move to specific
-# defines which links of the sidebar are translatable
-$wgForceUIMsgAsContentMsg = array( 'mainpage-url', 'mapfeatures-url', 'contributors-url', 'helppage', 'blogs-url', 'shop-url', 'sitesupport-url' );
+$wgAllowExternalImagesFrom = [
+ 'http://tile.openstreetmap.org/',
+ 'https://tile.openstreetmap.org',
+ 'http://josm.openstreetmap.de/'
+];
+
+$wgNoFollowDomainExceptions = [
+ 'www.openstreetmap.org',
+ 'josm.openstreetmap.de',
+ 'taginfo.openstreetmap.org',
+ 'blog.openstreetmap.org',
+ 'forum.openstreetmap.org',
+ 'community.openstreetmap.org',
+ 'lists.openstreetmap.org',
+ 'help.openstreetmap.org',
+ 'switch2osm.org',
+ 'wiki.osmfoundation.org',
+ 'www.openstreetmap.us',
+ 'learnosm.org',
+ 'nominatim.org',
+ 'openstreetmap.community',
+ 'www.openstreetbrowser.org',
+ 'openinframap.org',
+ 'leafletjs.com'
+];
# FIXME - move to specific
$wgAllowUserJs = TRUE;
$wgAllowUserCss = TRUE;
-# FIXME - move to specific
+# Raise expensive lua (and other function) call limits to match WP
+# Docs: https://www.mediawiki.org/wiki/Manual:$wgExpensiveParserFunctionLimit
+# Wikipedia's Config: https://noc.wikimedia.org/conf/highlight.php?file=CommonSettings.php
+$wgExpensiveParserFunctionLimit = 500;
+
+
+<% if @mediawiki[:site_notice] -%>
+$wgSiteNotice = "<%= @mediawiki[:site_notice] %>";
+<% end -%>
+<% if @mediawiki[:site_readonly] -%>
+$wgReadOnly = "<%= @mediawiki[:site_readonly] %>";
+<% end -%>
+
+<% if @name == "wiki.openstreetmap.org" -%>
# DE
define('NS_LANG_DE', 200);
$wgExtraNamespaces[NS_LANG_DE] = 'DE';
$wgExtraNamespaces[NS_LANG_JA_TALK] = 'JA_talk';
$wgNamespacesWithSubpages[NS_LANG_JA_TALK] = TRUE;
+# Proposal
+# namespace features a specific search weight defined at
+# cookbooks/mediawiki/templates/default/mw-ext-CirrusSearch.inc.php.erb
+define('NS_PROPOSAL', 3000);
+$wgExtraNamespaces[NS_PROPOSAL] = 'Proposal';
+$wgNamespacesWithSubpages[NS_PROPOSAL] = TRUE;
+$wgContentNamespaces[] = NS_PROPOSAL;
+define('NS_PROPOSAL_TALK', 3001);
+$wgExtraNamespaces[NS_PROPOSAL_TALK] = 'Proposal_talk';
+$wgNamespacesWithSubpages[NS_PROPOSAL_TALK] = TRUE;
+
$wgNamespacesToBeSearchedDefault[NS_LANG_DE] = TRUE;
$wgNamespacesToBeSearchedDefault[NS_LANG_FR] = TRUE;
$wgNamespacesToBeSearchedDefault[NS_LANG_ES] = TRUE;
$wgNamespacesToBeSearchedDefault[NS_LANG_NL] = TRUE;
$wgNamespacesToBeSearchedDefault[NS_LANG_RU] = TRUE;
$wgNamespacesToBeSearchedDefault[NS_LANG_JA] = TRUE;
+$wgNamespacesToBeSearchedDefault[NS_PROPOSAL] = TRUE;
+# defines which links of the sidebar are translatable
+$wgForceUIMsgAsContentMsg = array( 'mainpage-url', 'mapfeatures-url', 'contributors-url', 'helppage', 'blogs-url', 'shop-url', 'sitesupport-url' );
+<% end -%>
-# Raise expensive lua (and other function) call limits to match WP
-# Docs: https://www.mediawiki.org/wiki/Manual:$wgExpensiveParserFunctionLimit
-# Wikipedia's Config: https://noc.wikimedia.org/conf/highlight.php?file=CommonSettings.php
-$wgExpensiveParserFunctionLimit = 500;
-
+# load extensions
+<% Dir.glob("#{@directory}/LocalSettings.d/*.php") do |file| -%>
+<%= "require_once('#{file}');" %>
+<% end -%>
-<% if @mediawiki[:site_notice] -%>
-$wgSiteNotice = "<%= @mediawiki[:site_notice] %>";
+<% if @name == "wiki.openstreetmap.org" -%>
+# wiki.openstreetmap.org specific config loaded after extensions
+$wgRCWatchCategoryMembership = true;
<% end -%>
-<% if @mediawiki[:site_readonly] -%>
-$wgReadOnly = "<%= @mediawiki[:site_readonly] %>";
+
+<% if not(@mediawiki[:private_accounts]) and not(@mediawiki[:private_site]) -%>
+# require user confirmation for certain actions
+$wgGroupPermissions['user']['move'] = false;
+$wgGroupPermissions['user']['movefile'] = false;
+$wgGroupPermissions['user']['move-categorypages'] = false;
+$wgGroupPermissions['user']['upload'] = false;
+$wgGroupPermissions['autoconfirmed']['move'] = true;
+$wgGroupPermissions['autoconfirmed']['movefile'] = true;
+$wgGroupPermissions['autoconfirmed']['move-categorypages'] = true;
+$wgGroupPermissions['autoconfirmed']['upload'] = true;
+# Autopromote users to autoconfirmed
+$wgAutoConfirmAge = 345600; // 4 days
+$wgAutoConfirmCount = 10;
+
+# user group "confirmed" with identical rights as "autoconfirmed", but assigned manually by sysops
+$wgGroupPermissions['confirmed'] = $wgGroupPermissions['autoconfirmed'];
+$wgAddGroups['sysop'][] = 'confirmed';
+$wgRemoveGroups['sysop'][] = 'confirmed';
<% end -%>
-<% Dir.glob("#{@directory}/LocalSettings.d/*.php") do |file| -%>
-<%= "require_once('#{file}');" %>
+<% if @mediawiki[:private_accounts] or @mediawiki[:private_site] -%>
+# disable automatic confirmation of users, grant all "autoconfirmed" rights to all users
+$wgAutoConfirmAge = 0;
+$wgAutoConfirmCount = 0;
+$wgGroupPermissions['user'] = array_merge( $wgGroupPermissions['user'], $wgGroupPermissions['autoconfirmed'] );
+
+unset( $wgGroupPermissions['autoconfirmed'] );
+unset( $wgRevokePermissions['autoconfirmed'] );
+unset( $wgAddGroups['autoconfirmed'] );
+unset( $wgRemoveGroups['autoconfirmed'] );
+unset( $wgGroupsAddToSelf['autoconfirmed'] );
+unset( $wgGroupsRemoveFromSelf['autoconfirmed'] );
<% end -%>
+
+# Increase curl timeout to allow parsoid requests to heavy pages like Map Features
+# Mediawiki 1.38 has fix to allow this to be set by $wgVirtualRestConfig
+# https://phabricator.wikimedia.org/T285478
+$wgHTTPTimeout = 240;
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
- CustomLog /var/log/apache2/<%= @name %>-secure-access.log combined
- ErrorLog /var/log/apache2/<%= @name %>-secure-error.log
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
+ ErrorLog /var/log/apache2/<%= @name %>-error.log
DocumentRoot <%= @directory %>
+ AllowEncodedSlashes NoDecode
+
ProxyTimeout 300
RewriteCond %{SERVER_NAME} !=<%= @name %>
RewriteRule ^/(.*)$ https://<%= @name %>/$1 [R=permanent]
- RedirectMatch 301 ^/$ /wiki/Main_Page
-
- #Historical Compatibility Links
+ # Historical Compatibility Links
RedirectMatch 301 ^/index\.php$ /w/index.php
RedirectMatch 301 ^/index\.php/(.*)$ /wiki/$1
RedirectMatch 301 ^/skins/(.*)$ /w/skins/$1
RedirectMatch 301 ^/api\.php$ /w/api.php
RedirectMatch 301 ^/opensearch_desc\.php$ /w/opensearch_desc.php
- #Support Wikidata redirects based on Wikimedia's redirects:
+ # Support Wikidata redirects based on Wikimedia's redirects:
# https://github.com/wikimedia/puppet/blob/production/modules/mediawiki/files/apache/sites/wikidata-uris.incl
RedirectMatch 301 ^/entity/statement/([QqPp]\d+).*$ /wiki/Special:EntityData/$1
RedirectMatch 301 ^/value/(.*)$ /wiki/Special:ListDatatypes
Alias /wiki <%= @directory %>/w/index.php
- #Support /pagename -> /wiki/pagename
+ # Support /pagename -> /wiki/pagename
RewriteEngine on
+ RewriteRule ^/$ /w/index.php?title=Main_Page [L,QSA]
RewriteCond %{REQUEST_URI} !^/w/
RewriteCond %{REQUEST_URI} !^/wiki/
RewriteCond %{REQUEST_URI} !^/index\.php
RewriteCond %{REQUEST_URI} !^/entity/
RewriteCond %{REQUEST_URI} !^/value/
RewriteCond %{REQUEST_URI} !^/reference/
- RewriteCond %{REQUEST_URI} !^/prop/
- RewriteCond %{REQUEST_URI} !^/dump/
+ RewriteCond %{REQUEST_URI} !^/prop/
+ RewriteCond %{REQUEST_URI} !^/dump/
RewriteCond %{REQUEST_URI} !^/server-status
+ RewriteCond %{REQUEST_URI} !^/server-info
RewriteCond %{REQUEST_URI} !^/.well-known/
RewriteCond %{LA-U:REQUEST_FILENAME} !-f
RewriteCond %{LA-U:REQUEST_FILENAME} !-d
Require all granted
<FilesMatch ".+\.ph(ar|p|tml)$">
- SetHandler "proxy:unix:/run/php/<%= @name %>.sock|fcgi://127.0.0.1"
+ SetHandler "proxy:unix:/run/php/php-<%= @name %>-fpm.sock|fcgi://127.0.0.1"
</FilesMatch>
</Directory>
"skins/*/composer.json"
]
}
+ },
+ "require": {
+ "guzzlehttp/psr7": "2.4.5"
}
}
echo 'password=<%= @database_params[:password] %>' >> $T/mysqldump.opts
mysqldump --defaults-file=$T/mysqldump.opts --opt --skip-lock-tables --single-transaction --no-tablespaces "<%= @database_params[:name] %>" | lz4 -9 > $T/wiki-<%= @name %>-$D/wiki.sql.lz4
ln -s <%= @directory %> $T/wiki-<%= @name %>-$D/www
-nice tar --create --dereference --directory=$T --warning=no-file-changed --exclude=wiki-<%= @name %>-$D/www/w/images/thumb --exclude=wiki-<%= @name %>-$D/www/w/.git --exclude=wiki-<%= @name %>-$D/www/w/extensions/*/.git wiki-<%= @name %>-$D | nice gzip --rsyncable -9 > $T/$B
+nice tar --create --dereference --directory=$T --warning=no-file-changed --warning=no-file-removed --exclude=wiki-<%= @name %>-$D/www/w/images/thumb --exclude=wiki-<%= @name %>-$D/www/w/.git --exclude=wiki-<%= @name %>-$D/www/w/extensions/*/.git --exclude=wiki-<%= @name %>-$D/www/dump wiki-<%= @name %>-$D | nice gzip --rsyncable -9 > $T/$B
nice rsync --preallocate --fuzzy $T/$B backup::backup
rm -rf $T
<?php
# DO NOT EDIT - This file is being maintained by Chef
-wfLoadExtensions( array( 'ConfirmEdit', 'ConfirmEdit/ReCaptchaNoCaptcha' ) );
-$wgCaptchaClass = 'ReCaptchaNoCaptcha';
-$wgReCaptchaSendRemoteIP = true;
-$wgReCaptchaSiteKey = '<%= @public_key %>';
-$wgReCaptchaSecretKey = '<%= @private_key %>';
-
-$wgCaptchaTriggers['addurl'] = true;
-$wgCaptchaTriggers['create'] = true;
+wfLoadExtensions( array( 'ConfirmEdit', 'ConfirmEdit/hCaptcha' ) );
+$wgHCaptchaSendRemoteIP = true;
+$wgHCaptchaSiteKey = '<%= @public_key %>';
+$wgHCaptchaSecretKey = '<%= @private_key %>';
$wgGroupPermissions['autoconfirmed']['skipcaptcha'] = true;
+$wgGroupPermissions['bot' ]['skipcaptcha'] = true;
+$wgGroupPermissions['sysop' ]['skipcaptcha'] = true;
+
+$wgRateLimits['badcaptcha']['newbie'] = [ 100, 86400 ];
$wgSpamBlacklistFiles = array(
'https://meta.wikimedia.org/w/index.php?title=Spam_blacklist&action=raw&sb_ver=1'
);
+# log hits, but allow only administrators to view them
+$wgLogSpamBlacklistHits = true;
+$wgGroupPermissions['user']['spamblacklistlog'] = false;
+$wgGroupPermissions['sysop']['spamblacklistlog'] = true;
'src' => 'https://meta.wikimedia.org/w/index.php?title=Title_blacklist&action=raw',
),
);
+# log hits, but allow only administrators to view them
+$wgTitleBlacklistLogHits = true;
+$wgGroupPermissions['user']['titleblacklistlog'] = false;
+$wgGroupPermissions['sysop']['titleblacklistlog'] = true;
<?php
-$wgVirtualRestConfig['modules']['parsoid'] = array(
- 'url' => 'http://localhost:8142'
-);
-$wgVirtualRestConfig['modules']['parsoid']['forwardCookies'] = true;
-
-require_once($IP .'/extensions/VisualEditor/VisualEditor.php');
-
-// Enable by default for everybody
-$wgDefaultUserOptions['visualeditor-enable'] = 1;
-
-// Don't allow users to disable it
-// $wgHiddenPrefs[] = 'visualeditor-enable';
+wfLoadExtension( 'VisualEditor' );
+++ /dev/null
-<?php
-# DO NOT EDIT - This file is being maintained by Chef
-require_once($IP .'/extensions/osmtaginfo/osmtaginfo.php');
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-worker_heartbeat_timeout: 300000
-
-logging:
- level: info
-
-#metrics:
-# type: log
-
-services:
- - module: src/lib/index.js
- entrypoint: apiServiceWorker
- conf:
- # For backwards compatibility, and to continue to support non-static
- # configs for the time being, optionally provide a path to a
- # localsettings.js file. See localsettings.example.js
- #localsettings: ./localsettings.js
-
- # Set your own user-agent string
- # Otherwise, defaults to:
- # 'Parsoid/<current-version-defined-in-package.json>'
- #userAgent: 'My-User-Agent-String'
-
- # Configure Parsoid to point to your MediaWiki instances.
- mwApis:
- # - # This is the only required parameter,
- # the URL of you MediaWiki API endpoint.
- # uri: 'http://localhost/w/api.php'
- # The "domain" is used for communication with Visual Editor
- # and RESTBase. It defaults to the hostname portion of
- # the `uri` property below, but you can manually set it
- # to an arbitrary string.
- # domain: 'localhost' # optional
- # To specify a proxy (or proxy headers) specific to this prefix
- # (which overrides defaultAPIProxyURI). Alternatively, set `proxy`
- # to `null` to override and force no proxying when a default proxy
- # has been set.
- #proxy:
- # uri: 'http://my.proxy:1234/'
- # headers: # optional
- # 'X-Forwarded-Proto': 'https'
-<% node[:mediawiki][:sites].keys.sort.each do |site_url| -%>
- - # This is the only required parameter,
- uri: 'https://<%= site_url %>/w/api.php'
-<% end -%>
-
- # We pre-define wikipedias as 'enwiki', 'dewiki' etc. Similarly
- # for other projects: 'enwiktionary', 'enwikiquote', 'enwikibooks',
- # 'enwikivoyage' etc.
- # The default for this is false. Uncomment the line below if you want
- # to load WMF's config for wikipedias, etc.
- #loadWMF: true
-
- # A default proxy to connect to the API endpoints.
- # Default: undefined (no proxying).
- # Overridden by per-wiki proxy config in setMwApi.
- #defaultAPIProxyURI: 'http://proxy.example.org:8080'
-
- # Enable debug mode (prints extra debugging messages)
- #debug: true
-
- # Use the PHP preprocessor to expand templates via the MW API (default true)
- #usePHPPreProcessor: false
-
- # Use selective serialization (default false)
- useSelser: true
-
- # Allow cross-domain requests to the API (default '*')
- # Sets Access-Control-Allow-Origin header
- # disable:
- #allowCORS: false
- # restrict:
- #allowCORS: 'some.domain.org'
-
- # Allow override of port/interface:
- #serverPort: 8000
- #serverInterface: '127.0.0.1'
-
- # Enable linting of some wikitext errors to the log
- #linting: true
- # Send lint errors to MW API instead of to the log
- #linterSendAPI: false
-
- # Require SSL certificates to be valid (default true)
- # Set to false when using self-signed SSL certificates
- #strictSSL: false
-
- # Use a different server for CSS style modules.
- # Leaving it undefined (the default) will use the same URI as the MW API,
- # changing api.php for load.php.
- #modulesLoadURI: 'http://example.org/load.php'
version "1.0.0"
supports "ubuntu"
-depends "munin"
depends "prometheus"
# limitations under the License.
#
-include_recipe "munin"
include_recipe "prometheus"
package "memcached"
notifies :restart, "service[memcached]"
end
-munin_plugin_conf "memcached_multi" do
- template "munin.erb"
-end
-
-%w[bytes commands conns evictions items memory].each do |stat|
- munin_plugin "memcached_multi_#{stat}" do
- target "memcached_multi_"
- end
-end
-
prometheus_exporter "memcached" do
port 9150
options "--memcached.address=#{node[:memcached][:ip_address]}:#{node[:memcached][:tcp_port]} --memcached.pid-file=/run/memcached/memcached.pid"
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-[memcached_multi_*]
-user nobody
-env.host <%= node[:memcached][:ip_address] %>
-env.port <%= node[:memcached][:tcp_port] %>
+++ /dev/null
-# Munin Cookbook
-
-This cookbook configures munin, which we use for server monitoring at
-[munin.openstreetmap.org](https://munin.openstreetmap.org). The cookbook
-contains two recipes:
-
-* default - installs and configures munin-node on each machine.
-* server - configures the central munin server
-
-Additionally two providers are defined - munin_plugin and munin_plugin_conf, for
-configuring individual munin plugins.
+++ /dev/null
-default[:munin][:allow] = []
-default[:munin][:graphs] = {}
-default[:munin][:plugins] = {}
+++ /dev/null
-[api_calls_num]
-user root
+++ /dev/null
-[chef_*]
-user chefrepo
+++ /dev/null
-[hpasmcli2_*]
-user root
+++ /dev/null
-#!/usr/bin/ruby
-
-require "rubygems"
-require "date"
-require "hpricot"
-require "open-uri"
-
-def uris_from_status(server)
- file = open("http://#{server}/server-status").read
- doc = Hpricot.parse(file)
- tables = doc / "table"
- rows = (tables[1] / "tr")[1..-1]
- data = rows.collect { |r| (r / "td").collect(&:inner_html) }
- # filter where the PID is numeric, status is 'W' and host matches the server
- matching_data = data.select { |r| r[1].to_i.positive? && r[3].match(/W/) && r[12].match(server) }
- # return only the URI part
- matching_data.collect { |r| r[13] }
-end
-
-CALL_TYPES = {
- :map => "Map API calls",
- :upload => "Changeset diff uploads",
- :amf => "AMF API calls",
- :history => "Element history fetches",
- :full => "Full element fetches",
- :trkpts => "GPX trackpoints calls",
- :web => "Web site traffic",
- :other => "Other API calls"
-}.freeze
-
-def categorise_uri(line)
- uri = line.split(" ")[1]
-
- case uri
- when %r{api/0\.6/map} then :map
- when %r{api/0\.6/changeset/[0-9]*/upload} then :upload
- when %r{api/0\.6/amf} then :amf
- when %r{api/0\.6/(node|way|relation)/[0-9]*/history} then :history
- when %r{api/0\.6/(node|way|relation)/[0-9]*/full} then :full
- when %r{api/0\.6/trackpoints} then :trkpts
- when %r{api/0\.6/} then :other
- else :web
- end
-end
-
-server = $PROGRAM_NAME.match("api_calls_(.*)")[1]
-
-if ARGV[0] == "config"
- puts "graph_title Active requests"
- puts "graph_vlabel Number of requests"
- puts "graph_category api"
- CALL_TYPES.each { |k, v| puts "#{k}.label #{v}" }
-
-else
- counts = uris_from_status(server)
- .collect { |x| categorise_uri(x) }
- .each_with_object({}) do |e, h|
- if h.key? e
- h[e] += 1
- else
- h[e] = 1
- end
- end
-
- CALL_TYPES.each_key do |type|
- count = counts[type] || 0
- puts "#{type}.value #{count}"
- end
-end
+++ /dev/null
-#!/usr/bin/ruby
-
-require "json"
-
-CALL_TYPES = {
- :map => "Map API calls",
- :upload => "Changeset diff uploads",
- :amf => "AMF API calls",
- :history => "Element history fetches",
- :full => "Full element fetches",
- :trkpts => "GPX trackpoints calls",
- :web => "Web site traffic",
- :other => "Other API calls"
-}.freeze
-
-if ARGV[0] == "config"
- puts "graph_title Requests processed"
- puts "graph_args --base 1000"
- puts "graph_vlabel Number of requests per ${graph_period}"
- puts "graph_category api"
-
- CALL_TYPES.each do |type, label|
- puts "#{type}.label #{label}"
- puts "#{type}.type DERIVE"
- puts "#{type}.min 0"
- end
-else
- statistics = JSON.parse(File.read("/srv/www.openstreetmap.org/rails/tmp/statistics.json"))
-
- CALL_TYPES.each_key do |type|
- count = statistics["uri"][type.to_s] || 0
- puts "#{type}.value #{count}"
- end
-end
+++ /dev/null
-#!/usr/bin/ruby
-
-require "json"
-
-HTTP_STATUSES = {
- "200" => "OK",
- "206" => "Partial Content",
- "301" => "Moved Permanently",
- "302" => "Found",
- "303" => "See Other",
- "304" => "Not Modified",
- "400" => "Bad Request",
- "401" => "Unauthorized",
- "403" => "Forbidden",
- "404" => "Not Found",
- "405" => "Method Not Allowed",
- "408" => "Request Timeout",
- "409" => "Conflict",
- "410" => "Gone",
- "412" => "Precondition Failed",
- "416" => "Requested Range Not Satisfiable",
- "422" => "Unprocessable Entity",
- "500" => "Internal Server Error",
- "502" => "Bad Gateway",
- "503" => "Service Unavailable",
- "509" => "Bandwidth Limit Exceeded"
-}.freeze
-
-if ARGV[0] == "config"
- puts "graph_title HTTP response codes"
- puts "graph_args --base 1000"
- puts "graph_vlabel Number of requests per ${graph_period}"
- puts "graph_category api"
-
- HTTP_STATUSES.each do |code, label|
- puts "http#{code}.label #{code} #{label}"
- puts "http#{code}.type DERIVE"
- puts "http#{code}.min 0"
- end
-else
- statistics = JSON.parse(File.read("/srv/www.openstreetmap.org/rails/tmp/statistics.json"))
-
- HTTP_STATUSES.each_key do |code|
- count = statistics["status"][code] || 0
- puts "http#{code}.value #{count}"
- end
-end
+++ /dev/null
-#!/usr/bin/ruby
-
-require "rubygems"
-require "date"
-require "hpricot"
-require "open-uri"
-
-def uri_and_times_from_status(server)
- file = open("http://#{server}/server-status").read
- doc = Hpricot.parse(file)
- tables = doc / "table"
- rows = (tables[1] / "tr")[1..-1]
- data = rows.collect { |r| (r / "td").collect(&:inner_html) }
- # filter where the PID is numeric, status is 'W' and host matches the server
- matching_data = data.select { |r| r[1].to_i.positive? && r[3].match(/W/) && r[12].match(server) }
- # return URI and number of seconds processing for each request
- matching_data.collect { |r| [r[13], r[5].to_i] }
-end
-
-CALL_TYPES = {
- :map => "Map API calls",
- :upload => "Changeset diff uploads",
- :amf => "AMF API calls",
- :history => "Element history fetches",
- :full => "Full element fetches",
- :trkpts => "GPX trackpoints calls",
- :web => "Web site traffic",
- :other => "Other API calls"
-}.freeze
-
-def categorise_uri(line)
- uri = line.split(" ")[1]
-
- case uri
- when %r{api/0\.6/map} then :map
- when %r{api/0\.6/changeset/[0-9]*/upload/} then :upload
- when %r{api/0\.6/amf} then :amf
- when %r{api/0\.6/(node|way|relation)/[0-9]*/history} then :history
- when %r{api/0\.6/(node|way|relation)/[0-9]*/full} then :full
- when %r{api/0\.6/trackpoints} then :trkpts
- when %r{api/0\.6/} then :other
- else :web
- end
-end
-
-server = $PROGRAM_NAME.match("api_waits_(.*)")[1]
-
-if ARGV[0] == "config"
- puts "graph_title Wait times for active requests"
- puts "graph_vlabel Average time of requests"
- puts "graph_category api"
- CALL_TYPES.each { |k, v| puts "#{k}.label #{v}" }
-
-else
- counts = uri_and_times_from_status(server)
- .collect { |x, y| [categorise_uri(x), y] }
- .each_with_object({}) do |e, h|
- category, time = e
- if h.key? category
- h[category] += [time]
- else
- h[category] = [time]
- end
- end
-
- CALL_TYPES.each_key do |type|
- count = counts[type] || [0]
- avg = count.inject(0) { |acc, elem| acc + elem } / (1.0 * count.length)
- puts "#{type}.value #{avg}"
- end
-end
+++ /dev/null
-#!/usr/bin/ruby
-
-require "json"
-
-nodes = JSON.parse(IO.popen(["knife", "status", "-c", "/var/lib/chef/.chef/knife.rb", "-F", "json"]).read).sort_by { |node| node["name"] }
-
-if ARGV[0] == "config"
- puts "graph_title Chef node status"
- puts "graph_args --base 1000 --logarithmic"
- puts "graph_vlabel Time since last checkin"
- puts "graph_category chef"
-
- nodes.each do |node|
- name = node["name"].split(".").first
-
- puts "#{name}.label #{name}"
- puts "#{name}.type GAUGE"
- puts "#{name}.min 0"
- puts "#{name}.warning 14400"
- puts "#{name}.critical 43200"
- end
-else
- nodes.each do |node|
- name = node["name"].split(".").first
- time = Time.now.to_f - node["ohai_time"]
-
- puts "#{name}.value #{time}"
- end
-end
+++ /dev/null
-#!/bin/sh
-
-: <<=cut
-
-=head1 NAME
-
-parse Chrony Tracking output for timeserver status information
-
-=head1 APPLICABLE SYSTEMS
-
-Any system with a local chronyd service.
-
-=head1 CONFIGURATION
-
-No configuration.
-
-=head1 MAGIC MARKERS
-
- #%# family=auto
- #%# capabilities=autoconf
-
-=head1 VERSION
-
-Revision 0.1 2008/08/23 13:06:00 joti
-
- First version only chronyc tracking, autodetection included.
-
-Revision 0.2 2008/10/11 16:09:00 joti
-
- Added scaling of other values to match with frequency, added more description to fields
-
-Revision 0.3 2014/02/16 zjttoefs
-
- reduce forking by using awk
- do not limit output precision
- add stratum monitoring
- detect slow/fast time or freqency and adjust sign of value accordingly
- remove commented out code
-
-Revision 0.4 2016/11/10 Lars Kruse
-
- rewrite field handling
- use "which" for "chronyc" location
- switch from "bash" to "sh"
- fix exit code of failing "autoconf"
-
-=head1 AUTHOR
-
- joti
- zjttoefs
- Lars Kruse <devel@sumpfralle.de>
-
-=cut
-
-CHRONYC="$(which chronyc | head -1)"
-
-# Frequency has extremely higher values than other. Therefore they are fitted by scaling via suitable factors.
-# field definitions:
-# - munin fieldname
-# - factor for graph visualization (all values are supposed to reach a similar dimension)
-# - regular expression of the chrony output line (may not contain whitespace, case insensitive)
-# - label (may include "%d" for including the factor; may contain whitespace)
-fields="stratum 1 ^Stratum Stratum
- systime 1000 ^System.time System Time (x%d)
- frequency 1 ^Frequency Frequency (ppm)
- residualfreq 100 ^Residual.freq Residual Freq (ppm, x%d)
- skew 100 ^Skew Skew (ppm, x%d)
- rootdelay 1000 ^Root.delay Root delay (seconds, x%d)
- rootdispersion 1000 ^Root.dispersion Root dispersion (seconds, x%d)"
-
-# chrony example output (v2.4.1):
-# Reference ID : 131.188.3.221 (ntp1.rrze.uni-erlangen.de)
-# Stratum : 2
-# Ref time (UTC) : Thu Nov 10 22:39:50 2016
-# System time : 0.000503798 seconds slow of NTP time
-# Last offset : +0.000254355 seconds
-# RMS offset : 0.002186779 seconds
-# Frequency : 17.716 ppm slow
-# Residual freq : +0.066 ppm
-# Skew : 4.035 ppm
-# Root delay : 0.042980 seconds
-# Root dispersion : 0.005391 seconds
-# Update interval : 258.4 seconds
-# Leap status : Normal
-
-
-if [ "$1" = "autoconf" ]; then
- if [ -n "$CHRONYC" ] && [ -x "$CHRONYC" ]; then
- echo yes
- else
- echo "no (missing 'chronyc' executable)"
- fi
- exit 0
-fi
-
-if [ "$1" = "config" ]; then
- echo 'graph_title Chrony Tracking Stats'
- echo 'graph_args --base 1000 -l 0'
- echo 'graph_vlabel (seconds,ppm)'
- echo 'graph_category time'
- echo "$fields" | while read fieldname factor regex label; do
- # insert the factor, if "%d" is part of the label
- printf "${fieldname}.label $label\n" "$factor"
- echo "${fieldname}.type GAUGE"
- done
- exit 0
-fi
-
-chrony_status="$("$CHRONYC" tracking)"
-echo "$fields" | while read fieldname factor regex label; do
- status_line="$(echo "$chrony_status" | grep -i -- "$regex " | cut -d ":" -f 2-)"
- if [ -z "$status_line" ]; then
- value="U"
- else
- # the keyword "slow" indicates negative values
- value="$(echo "$status_line" | awk '{ /slow/ ? SIGN=-1 : SIGN=1; print $1 * SIGN * '"$factor"' }')"
- fi
- echo "${fieldname}.value $value"
-done
+++ /dev/null
-#!/usr/bin/perl -w
-
-=head1 NAME
-
-fw_conntrack - Plugin to monitor the number of tracked connections
-through a Linux 2.4/2.6 firewall
-
-=head1 CONFIGURATION
-
-This plugin must run with root privileges
-
-=head2 CONFIGURATION EXAMPLE
-
-/etc/munin/plugin-conf.d/global or other file in that dir must contain:
-
- [fw_*]
- user root
-
-=head1 NOTES
-
-ESTABLISHED+FIN_WAIT+TIME_WAIT+SYN_SENT+UDP are the most interesting
-connections.
-
-The total list also includes SYN_RECV, CLOSE, CLOSE_WAIT, LAST_ACK and
-LISTEN, but these were not (often) observed on my firewall.
-
-TOTAL is the total number of tracked connections.
-
-ASSURED and UNREPLIED connections are complimentary subsets of
-ESTABLISHED.
-
-ASSURED is after ACK is seen after SYN_RECV. Therefore ASSURED is
-plotted but not UNREPLIED.
-
-Note that the plugin depends on the netfilter "conntrack" userspace tool.
-It comes from http://conntrack-tools.netfilter.org/
-
-=head1 AUTHORS
-
-=over
-
-=item 2004.05.05: Initial version by Nicolai Langfeldt, Linpro AS, Oslo, Norway
-
-=item 2004.05.06: Enhanced to count NATed connections after input from Xavier on munin-users list
-
-=item 2011.09.23: Perl version by Alex Tomlins
-
-=back
-
-=head1 LICENSE
-
-GPL
-
-=head1 MAGIC MARKERS
-
- #%# family=auto
- #%# capabilities=autoconf
-
-=cut
-
-use strict;
-use Munin::Plugin;
-
-my $conntrack = '/usr/sbin/conntrack';
-my $nf_conntrack_file = '/proc/net/nf_conntrack';
-my $ip_conntrack_file = '/proc/net/ip_conntrack';
-my @conntrack_max_files = qw(
- /proc/sys/net/nf_conntrack_max
- /proc/sys/net/netfilter/nf_conntrack_max
- /proc/sys/net/ipv4/ip_conntrack_max
- /proc/sys/net/ipv4/netfilter/ip_conntrack_max
-);
-
-if ( defined($ARGV[0]) and $ARGV[0] eq "autoconf" ) {
- if ( -x $conntrack or -r $nf_conntrack_file or -r $ip_conntrack_file) {
- print "yes\n";
- } else {
- print "no\n";
- }
- exit 0;
-}
-
-if ( defined($ARGV[0]) and $ARGV[0] eq "config" ) {
- print <<EOF;
-graph_title Connections through firewall
-graph_vlabel Connections
-graph_category network
-graph_args -l 0
-established.label Established
-established.type GAUGE
-established.draw AREA
-fin_wait.label FIN_WAIT
-fin_wait.type GAUGE
-fin_wait.draw STACK
-time_wait.label TIME_WAIT
-time_wait.type GAUGE
-time_wait.draw STACK
-syn_sent.label SYN_SENT
-syn_sent.type GAUGE
-syn_sent.draw STACK
-udp.label UDP connections
-udp.type GAUGE
-udp.draw STACK
-assured.label Assured
-assured.type GAUGE
-assured.draw LINE2
-nated.label NATed
-nated.type GAUGE
-nated.draw LINE1
-total.label Total
-total.type GAUGE
-total.graph no
-EOF
- my $max;
- foreach (@conntrack_max_files) {
- if ( -r $_) {
- chomp($max = `cat $_`);
- last;
- }
- }
- if ($max) {
- print "total.warning ", $max * 8 / 10, "\n";
- print "total.critical ", $max * 9 / 10, "\n";
- }
- exit 0;
-}
-
-my $command;
-if ( -x $conntrack) {
- $command = "$conntrack -L -o extended -f ipv4 2>/dev/null; $conntrack -L -o extended -f ipv6 2>/dev/null";
-} elsif ( -r $nf_conntrack_file ) {
- $command = "cat $nf_conntrack_file";
-} else {
- $command = "cat $ip_conntrack_file";
-}
-
-my %state = (
- 'ESTABLISHED' => 0,
- 'FIN_WAIT' => 0,
- 'TIME_WAIT' => 0,
- 'SYN_SENT' => 0,
- 'UDP' => 0,
- 'ASSURED' => 0,
- 'NATTED' => 0,
- 'TOTAL' => 0
-);
-open CMD, "$command|";
-while (<CMD>) {
- $state{'TOTAL'} ++;
- $state{'UDP'} ++ if /udp /;
- $state{'ASSURED'} ++ if /ASSURED/;
- if (/tcp \s*\d+\s+\d+\s+(\S+)/) {
- $state{$1} ++;
- }
- if (/src=(\S+)\s+dst=(\S+)\s+sport.*src=(\S+)\s+dst=(\S+)/) {
- $state{'NATTED'} ++ if $1 ne $4 or $2 ne $3;
- }
-}
-close CMD;
-
-print "established.value $state{'ESTABLISHED'}\n";
-print "fin_wait.value $state{'FIN_WAIT'}\n";
-print "time_wait.value $state{'TIME_WAIT'}\n";
-print "syn_sent.value $state{'SYN_SENT'}\n";
-print "udp.value $state{'UDP'}\n";
-print "assured.value $state{'ASSURED'}\n";
-print "nated.value $state{'NATTED'}\n";
-print "total.value $state{'TOTAL'}\n";
+++ /dev/null
-#!/usr/bin/perl -w
-
-=head1 NAME
-
-fw_forwarded_local - Plugin to monitor network connections.
-
-=head1 CONFIGURATION
-
-This plugin must run with root privileges
-
-=head2 CONFIGURATION EXAMPLE
-
-/etc/munin/plugin-conf.d/global or other file in that dir must contain:
-
- [fw_*]
- user root
-
-=head1 NOTES
-
-=over
-
-=item * forward: number of connections forwarded
-
-=item * local: number of connections for the host itself
-
-=back
-
-=head1 AUTHORS
-
-2011.09.23: Perl version by Alex Tomlins
-
-=head1 MAGIC MARKERS
-
- #%# family=auto
- #%# capabilities=autoconf
-
-=cut
-
-use strict;
-use Munin::Plugin;
-
-my $conntrack = '/usr/sbin/conntrack';
-my $nf_conntrack_file = '/proc/net/nf_conntrack';
-my $ip_conntrack_file = '/proc/net/ip_conntrack';
-
-if ( defined($ARGV[0]) and $ARGV[0] eq "autoconf" ) {
- if ( -x $conntrack or -r $nf_conntrack_file or -r $ip_conntrack_file) {
- print "yes\n";
- } else {
- print "no\n";
- }
- exit 0;
-}
-
-if ( defined($ARGV[0]) and $ARGV[0] eq "config" ) {
- print "graph_title ipconntrack\n";
- print "graph_args -l 0 --base 1000\n";
- print "graph_vlabel established connections\n";
- print "graph_category network\n";
- print "forward.label forward\n";
- print "forward.type GAUGE\n";
- print "local.label local\n";
- print "local.type GAUGE\n";
- exit 0;
-}
-
-my $command;
-if ( -x $conntrack) {
- $command = "$conntrack -L -o extended 2>/dev/null";
-} elsif ( -r $nf_conntrack_file ) {
- $command = "cat $nf_conntrack_file";
-} elsif (-r $ip_conntrack_file ) {
- $command = "cat $ip_conntrack_file";
-} else {
- die "Can't find conntrack information\n";
-}
-
-my $local = 0;
-my $forward = 0;
-open CMD, "$command|";
-while (<CMD>) {
- if (/ESTABLISHED\s+src=(\S+)\s+dst=(\S+)\s+sport.*src=(\S+)\s+dst=(\S+)/) {
- if ($1 eq $4) {
- $local++;
- } else {
- $forward++;
- }
- }
-}
-close CMD;
-
-print "forward.value $forward\n";
-print "local.value $local\n"
+++ /dev/null
-#!/usr/bin/env perl
-#
-# Plugin to monitor Proliant server health status using hpasmcli.
-#
-# Config variables:
-# user root -- requrired by hpasmcli
-# env.hpasmcli -- path to hpasmcli executable (optional)
-# env.degree -- Unit of temperatures (C or F / default value is C)
-#
-#
-# Author: Tsuyoshi Wada <mail@tuyo.jp>
-#
-# v1.0 2007/12/08 - First version
-#
-# Copyright (c) 2007 Tsuyoshi Wada
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# Magic markers
-#%# family=contrib
-#%# capabilities=autoconf suggest
-
-use strict;
-
-my $hpasmcli = exists $ENV{hpasmcli} ? $ENV{hpasmcli} : undef;
-$hpasmcli = `which hpasmcli` unless $hpasmcli;
-chomp $hpasmcli;
-$hpasmcli = undef unless -x $hpasmcli;
-my @dirs = qw(/usr/bin /usr/sbin /usr/local/bin /usr/local/sbin);
-until ($hpasmcli or @dirs == 0) {
- my $dir = shift @dirs;
- my $path = $dir.'/hpasmcli';
- $hpasmcli = $path if -x $path;
-}
-my $degree = exists $ENV{degree} ? $ENV{degree} : 'C';
-my $deg_name = $degree eq 'C' ? "Celsius": "Fahrenheit";
-
-if (defined($ARGV[0])) {
- if ($ARGV[0] eq 'autoconf') {
- if ($hpasmcli and -x $hpasmcli) {
- my @chk_result = `$hpasmcli -s \"help\"`;
- if ($? eq "0") {
- print "yes\n";
- exit 0;
- } else {
- my $reason = 'Unknown error';
- foreach my $line (@chk_result) {
- if ($line =~ /^ERROR/i) {
- chomp($line);
- $reason = $line;
- last;
- }
- }
- print "no ($reason)\n";
- exit 1;
- }
- } else {
- print "no (hpasmcli not found)\n";
- exit 1;
- }
- } elsif ($ARGV[0] eq 'suggest') {
- print "temp\nfans\n";
- exit 0;
- }
-}
-
-$0 =~ /hpasmcli2_(.+)*$/;
-my $show_target = $1;
-my @show_result = `$hpasmcli -s \"show $show_target\"`;
-my %output;
-
-if (defined($show_target) and $show_target eq 'temp') {
- foreach my $line (@show_result) {
- if ($line =~ /^#/) {
- $line =~ s/\s+/ /g;
- $line =~ s/^\s//g;
- my ($sensor, $loc, $temp, $threshold) = split(/\s/, $line);
- next if ($temp eq "-");
- $loc =~ s/\/|#//g;
- $temp = $degree eq 'C' ? (split(/\//, $temp))[0] : (split(/\//, $temp))[1];
- $temp =~ s/C|F//g;
- $threshold = $degree eq 'C' ? (split(/\//, $threshold))[0] : (split(/\//, $threshold))[1];
- $threshold =~ s/C|F//g;
- $sensor =~s/#//g;
- $output{$sensor} = {
- 'location' => lc($loc),
- 'temp' => $temp,
- 'threshold' => $threshold
- };
- }
- }
- if (defined($ARGV[0]) and $ARGV[0] eq 'config') {
- print "graph_title hpasm: Temperature\n";
- print "graph_args --base 1000 -l 0\n";
- print "graph_vlabel Degrees in $deg_name\n";
- print "graph_category sensors\n";
- print "graph_info This graph shows the temperatures as reported by hpasmcli.\n";
- foreach my $key (sort keys %output) {
- print "temp$key.label $output{$key}->{'location'}\n";
- print "temp$key.warning " . ($output{$key}->{'threshold'} * 0.85) . "\n";
- print "temp$key.critical $output{$key}->{'threshold'}\n";
- }
- } else {
- foreach my $key (sort keys %output) {
- print "temp$key.value $output{$key}->{'temp'}\n";
- }
- }
-} elsif (defined($show_target) and $show_target eq 'fans') {
- foreach my $line (@show_result) {
- if ($line =~ /^#/) {
- $line =~ s/\s+/ /g;
- $line =~ s/^\s//g;
- my ($fan, $loc, $present, $speed, $rate, $redundant, $partner, $pluggable) = split(/\s/, $line);
- next if ($present ne "Yes");
- $loc =~ s/\/|#//g;
- $rate =~ s/\%//g;
- my $threshold = '100';
- $fan =~s/#//g;
- $output{$fan} = {
- 'location' => lc($loc),
- 'rate' => $rate,
- 'threshold' => $threshold
- };
- }
- }
- if (defined($ARGV[0]) and $ARGV[0] eq 'config') {
- print "graph_title hpasm: Fans\n";
- print "graph_args --base 1000 -l 0\n";
- print "graph_vlabel of max (%)\n";
- print "graph_category sensors\n";
- print "graph_info This graph shows the info of fans as reported by hpasmcli.\n";
- foreach my $key (sort keys %output) {
- print "fan$key.label FAN$key $output{$key}->{'location'}\n";
- print "fan$key.warning " . ($output{$key}->{'threshold'} * 0.75) . "\n";
- print "fan$key.critical $output{$key}->{'threshold'}\n";
- }
- } else {
- foreach my $key (sort keys %output) {
- print "fan$key.value $output{$key}->{'rate'}\n";
- }
- }
-} else {
- die "Unknown target specified ($show_target)\n";
-}
-
-exit 0;
+++ /dev/null
-#!/usr/bin/perl
-#
-
-=head1 MEMCACHED
-
-Memcached - A Plugin to monitor Memcached Servers
-
-=head1 MUNIN CONFIGURATION
-
-[memcached_*]
- env.host 127.0.0.1 *default*
- env.port 11211 *default*
-
-=head2 MUNIN ENVIRONMENT CONFIGURATION EXPLANATION
-
- host = host we are going to monitor
- port = port we are connecting to, in order to gather stats
-
-=head1 NODE CONFIGURATION
-
-Please make sure you can telnet to your memcache servers and issue the
- following commands: stats
-
-Available Graphs contained in this Plugin
-
-bytes => This graphs the current network traffic in and out
-
-commands => This graphs the current commands being issued to the memcache machine.
-
-conns => This graphs the current, max connections as well as avg conns per sec avg conns per sec is derived from total_conns / uptime.
-
-evictions => This graphs the current evictions on the node.
-
-items => This graphs the current items and total items in the memcached node.
-
-memory => This graphs the current and max memory allocation.
-
-The following example holds true for all graphing options in this plugin.
- Example: ln -s /usr/share/munin/plugins/memcached_ /etc/munin/plugins/memcached_bytes
-
-=head1 ACKNOWLEDGEMENTS
-
-Thanks to dormando for putting up with me ;)
-
-=head1 AUTHOR
-
-Matt West < https://github.com/mhwest13/Memcached-Munin-Plugin >
-
-=head1 LICENSE
-
-GPLv2
-
-=head1 MAGIC MARKERS
-
-#%# family=auto
-#%# capabilities=autoconf suggest
-
-=cut
-
-use strict;
-use IO::Socket;
-
-my $host = $ENV{host} || "127.0.0.1";
-my $port = $ENV{port} || 11211;
-my $connection;
-
-my %stats;
-
-# This hash contains the information contained in two memcache commands
-# stats and stats settings.
-
-# So I was trying to figure out how to build this up, and looking at some good examples
-# I decided to use the format, or for the most part, the format from the mysql_ munin plugin
-# for Innodb by Kjell-Magne Ãierud, it just spoke ease of flexibility especially with multigraphs
-# thanks btw ;)
-#
-# %graphs is a container for all of the graph definition information. In here is where you'll
-# find the configuration information for munin's graphing procedure.
-# Format:
-#
-# $graph{graph_name} => {
-# config => {
-# # You'll find keys and values stored here for graph manipulation
-# },
-# datasrc => [
-# # Name: name given to data value
-# # Attr: Attribute for given value
-# { name => 'Name', (Attr) },
-# { ... },
-# ],
-# }
-my %graphs;
-
-$graphs{items} = {
- config => {
- args => '--base 1000 --lower-limit 0',
- vlabel => 'Items in Memcached',
- category => 'memcached',
- title => 'Items',
- info => 'This graph shows the number of items in use by memcached',
- },
- datasrc => [
- { name => 'curr_items', label => 'Current Items', min => '0' },
- {
- name => 'total_items',
- label => 'New Items',
- min => '0',
- type => 'DERIVE'
- },
- ],
-};
-
-$graphs{memory} = {
- config => {
- args => '--base 1024 --lower-limit 0',
- vlabel => 'Bytes Used',
- category => 'memcached',
- title => 'Memory Usage',
- info => 'This graph shows the memory consumption of memcached',
- },
- datasrc => [
- {
- name => 'limit_maxbytes',
- draw => 'AREA',
- label => 'Maximum Bytes Allocated',
- min => '0'
- },
- {
- name => 'bytes',
- draw => 'AREA',
- label => 'Current Bytes Used',
- min => '0'
- },
- ],
-};
-
-$graphs{bytes} = {
- config => {
- args => '--base 1000',
- vlabel => 'bits in (-) / out (+)',
- title => 'Network Traffic',
- category => 'memcached',
- info =>
-'This graph shows the network traffic in (-) / out (+) of the machine',
- order => 'bytes_read bytes_written',
- },
- datasrc => [
- {
- name => 'bytes_read',
- type => 'DERIVE',
- label => 'Network Traffic coming in (-)',
- graph => 'no',
- cdef => 'bytes_read,8,*',
- min => '0'
- },
- {
- name => 'bytes_written',
- type => 'DERIVE',
- label => 'Traffic in (-) / out (+)',
- negative => 'bytes_read',
- cdef => 'bytes_written,8,*',
- min => '0'
- },
- ],
-};
-
-$graphs{conns} = {
- config => {
- args => '--base 1000 --lower-limit 0',
- vlabel => 'Connections per ${graph_period}',
- category => 'memcached',
- title => 'Connections',
- info =>
-'This graph shows the number of connections being handled by memcached',
- order => 'curr_conns avg_conns',
- },
- datasrc => [
- { name => 'curr_conns', label => 'Current Connections', min => '0' },
- { name => 'avg_conns', label => 'Avg Connections', min => '0' },
- ],
-};
-
-$graphs{commands} = {
- config => {
- args => '--base 1000 --lower-limit 0',
- vlabel => 'Commands per ${graph_period}',
- category => 'memcached',
- title => 'Commands',
- info =>
- 'This graph shows the number of commands being handled by memcached',
- },
- datasrc => [
- {
- name => 'cmd_get',
- type => 'DERIVE',
- label => 'Gets',
- info => 'Cumulative number of retrieval reqs',
- min => '0'
- },
- {
- name => 'cmd_set',
- type => 'DERIVE',
- label => 'Sets',
- info => 'Cumulative number of storage reqs',
- min => '0'
- },
- {
- name => 'get_hits',
- type => 'DERIVE',
- label => 'Get Hits',
- info => 'Number of keys that were requested and found',
- min => '0'
- },
- {
- name => 'get_misses',
- type => 'DERIVE',
- label => 'Get Misses',
- info => 'Number of keys there were requested and not found',
- min => '0'
- },
- ],
-};
-
-$graphs{evictions} = {
- config => {
- args => '--base 1000 --lower-limit 0',
- vlabel => 'Evictions per ${graph_period}',
- category => 'memcached',
- title => 'Evictions',
- info => 'This graph shows the number of evictions per second',
- },
- datasrc => [
- {
- name => 'evictions',
- label => 'Evictions',
- info => 'Cumulative Evictions Across All Slabs',
- type => 'DERIVE',
- min => '0'
- },
- ],
-};
-
-##
-#### Config Check ####
-##
-
-if ( defined $ARGV[0] && $ARGV[0] eq 'config' ) {
-
- $0 =~ /(?:([^\/]+)_)?memcached_(.+)$/;
- my $prefix = $1 ? $1 : '';
- my $plugin = $2;
-
- die 'Unknown Plugin Specified: ' . ( $plugin ? $plugin : '' )
- unless $graphs{$plugin};
-
-# We need to fetch the stats before we do any config, cause its needed for multigraph
- fetch_stats();
-
- # Now lets go ahead and print out our config.
- do_config( $prefix, $plugin );
- exit 0;
-}
-
-##
-#### Autoconf Check ####
-##
-
-if ( defined $ARGV[0] && $ARGV[0] eq 'autoconf' ) {
-
- # Lets attempt to connect to memcached
- my $s = get_conn();
-
- # Lets check that we did connect to memcached
- if ( defined($s) ) {
- print "yes\n";
- exit 0;
- }
- else {
- print "no (unable to connect to $connection)\n";
- exit 0;
- }
-}
-
-##
-#### Suggest Check ####
-##
-
-if ( defined $ARGV[0] && $ARGV[0] eq 'suggest' ) {
-
- # Lets attempt to connect to memcached
- my $s = get_conn();
-
- # Lets check that we did connect to memcached
- if ( defined($s) ) {
- my @rootplugins =
- ( 'bytes', 'conns', 'commands', 'evictions', 'items', 'memory' );
- foreach my $plugin (@rootplugins) {
- print "$plugin\n";
- }
- exit 0;
- }
- else {
- print "no (unable to connect to $connection)\n";
- exit 0;
- }
-}
-
-##
-#### Well We aren't running (auto)config/suggest so lets print some stats ####
-##
-
-fetch_output();
-
-##
-#### Subroutines for printing info gathered from memcached ####
-##
-
-##
-#### This subroutine performs the bulk processing for printing statistics.
-##
-
-sub fetch_output {
-
- $0 =~ /(?:([^\/]+)_)?memcached_(.+)$/;
- my $prefix = $1 ? $1 : '';
- my $plugin = $2;
-
- die 'Unknown Plugin Specified: ' . ( $plugin ? $plugin : '' )
- unless $graphs{$plugin};
-
- # Well we need to actually fetch the stats before we do anything to them.
- fetch_stats();
-
- # Now lets go ahead and print out our output.
- print_root_output($plugin);
-
- return;
-}
-
-##
-#### This subroutine is for the root non-multigraph graphs which render on the main node page ####
-##
-
-sub print_root_output {
- my ($plugin) = (@_);
-
- my $graph = $graphs{$plugin};
-
- #print "graph memcached_$plugin\n";
-
- if ( $plugin ne 'conns' ) {
- foreach my $dsrc ( @{ $graph->{datasrc} } ) {
- my %datasrc = %$dsrc;
- while ( my ( $key, $value ) = each(%datasrc) ) {
- next if ( $key ne 'name' );
- my $output = $stats{$value};
- print "$dsrc->{name}.value $output\n";
- }
- }
- }
- else {
- my $output;
- foreach my $dsrc ( @{ $graph->{datasrc} } ) {
- my %datasrc = %$dsrc;
- while ( my ( $key, $value ) = each(%datasrc) ) {
- if ( $value eq 'curr_conns' ) {
- $output = $stats{curr_connections};
- }
- elsif ( $value eq 'avg_conns' ) {
- $output = sprintf( "%02d",
- $stats{total_connections} / $stats{uptime} );
- }
- else {
- next;
- }
- print "$dsrc->{name}.value $output\n";
- }
- }
- }
-
- return;
-}
-
-##
-#### Subroutines for printing out config information for graphs ####
-##
-
-##
-#### This subroutine does the bulk printing the config info per graph ####
-##
-
-sub do_config {
- my ( $prefix, $plugin ) = (@_);
- print_root_config( $prefix, $plugin );
-
- return;
-}
-
-##
-#### This subroutine is for the config info for non multigraph graphs which render on the main node page ####
-##
-
-sub print_root_config {
- my ( $prefix, $plugin ) = (@_);
-
- die 'Unknown Plugin Specified: ' . ( $plugin ? $plugin : '' )
- unless $graphs{$plugin};
-
- my $graph = $graphs{$plugin};
-
- my %graphconf = %{ $graph->{config} };
-
- #print "graph memcached_$plugin\n";
-
- while ( my ( $key, $value ) = each(%graphconf) ) {
- if ( $key eq 'title' ) {
- if ($prefix) {
- print "graph_$key " . ucfirst($prefix) . " $value\n";
- }
- else {
- print "graph_$key $value\n";
- }
- }
- else {
- print "graph_$key $value\n";
- }
- }
-
- foreach my $dsrc ( @{ $graph->{datasrc} } ) {
- my %datasrc = %$dsrc;
- while ( my ( $key, $value ) = each(%datasrc) ) {
- next if ( $key eq 'name' );
- print "$dsrc->{name}.$key $value\n";
- }
- }
-
- return;
-}
-
-##
-#### This subroutine returns a socket connection ####
-##
-
-sub get_conn {
- my $s = undef;
-
- # check if we want to use sockets instead of tcp
- my ($sock) = ( $host =~ /unix:\/\/(.+)$/ );
-
- if ($sock) {
- $connection = "unix:\/\/$sock";
- $s = IO::Socket::UNIX->new( Peer => $sock );
- }
- else {
- $connection = "$host:$port";
- $s = IO::Socket::INET->new(
- Proto => "tcp",
- PeerAddr => $host,
- PeerPort => $port,
- Timeout => 10,
- );
- }
-
- return $s;
-}
-
-##
-#### This subroutine actually performs the data fetch for us ####
-#### These commands do not lock up Memcache at all ####
-##
-
-sub fetch_stats {
- my $s = get_conn();
-
- die "Error: Unable to Connect to $connection\n" unless $s;
-
- print $s "stats\r\n";
-
- while ( my $line = <$s> ) {
- if ( $line =~ /STAT\s(.+?)\s(\d+)/ ) {
- my ( $skey, $svalue ) = ( $1, $2 );
- $stats{$skey} = $svalue;
- }
- last if $line =~ /^END/;
- }
-}
+++ /dev/null
-#!/usr/bin/perl
-#
-
-=head1 MEMCACHED MULTI
-
-Memcached Multi - A Plugin to monitor Memcached Servers (Multigraph)
-
- The common difference between this memcached Munin plugin and others that exists, is that
- others don't expose slab information from memcached, so you can better tune your memcached
- interaction / stability / etc. With this plugin we leverage multigraph capabilities in
- Munin to "hide" the slab information underneath of their parent graphs.
-
-=head1 MUNIN NODE CONFIGURATION
-
-The following configuration information can be overridden by placing environment definitions
- like shown here, in a file located in /etc/munin/plugin-conf.d
-
-[memcached_multi_*]
- env.host 127.0.0.1 *default*
- env.port 11211 *default*
- env.timescale 3 *default*
- env.cmds get set delete incr decr touch *default*
- env.leitime -1 *default*
-
-=head2 MUNIN NODE ENVIRONMENT CONFIGURATION EXPLANATION
-
- host = host we are going to monitor, this can be used to specify a unix socket.
- port = port we are connecting to, in order to gather stats
- timescale = what time frame do we want to format our graphs too
- cmds = cmd types to display on cmd graph, remove cmds you don't want displayed from list.
- leitime = setting this to 1 will re-enable slab eviction time graphs, see note below.
-
-=head2 BASIC TROUBLESHOOTING
-
-Please make sure you can telnet to your memcache servers and issue the
- following commands: stats, stats settings, stats items and stats slabs.
-
-=head2 PLUGIN INFORMATION
-
-Available Graphs contained in this Plugin
-
-bytes => This graphs the current network traffic in and out
-
-commands => I<MULTIGRAPH> This graphs the current commands being issued to the memcache machine.
- B<Multigraph breaks this down to per slab.>
-
-conns => This graphs the current, max connections as well as avg conns per sec avg conns per sec
- and is derived from total_conns / uptime.
-
-evictions => I<MULTIGRAPH> This graphs the current evictions on the node.
- B<Multigraph breaks this down to per slab.>
-
-items => I<MULTIGRAPH> This graphs the current items and total items in the memcached node.
- B<Multigraph breaks this down to per slab.>
-
-memory => I<MULTIGRAPH> This graphs the current and max memory allocation.
- B<Multigraph breaks this down to per slab.>
-
-unfetched => I<MULTIGRAPH> This graphs the number of items that were never touched by a
- get/incr/append/etc before being evicted or expiring from the cache.
- B<Multigraph breaks this down to per slab.>
-
-=head1 ADDITIONAL INFORMATION
-
-B<NOTE:> The slab plugin for LEI has been disabled since I believe the counters to be inaccurate,
- or perhaps not being updated as often I thought they would be. They can be re-enabled by
- setting an environment variable, see munin configuration section at the top.
-
-You will find that some of the graphs have LEI on them. This was done in order to save room
-on space for text and stands for B<Last Evicted Item>.
-
-The B<Timescale> variable formats certain graphs based on the following guidelines.
- 1 => Seconds
- 2 => Minutes
- 3 => Hours B<*Default*>
- 4 => Days
-
-=head1 ACKNOWLEDGEMENTS
-
-Thanks to dormando for putting up with me ;)
-
-=head1 AUTHOR
-
-Matt West < https://github.com/mhwest13/Memcached-Munin-Plugin >
-
-=head1 LICENSE
-
-GPLv2
-
-=head1 MAGIC MARKERS
-
-#%# family=auto
-#%# capabilities=autoconf suggest
-
-=cut
-
-use strict;
-use warnings;
-use IO::Socket;
-use Munin::Plugin;
-use File::Basename;
-
-if ( basename($0) !~ /(?:([^\/]+)_)?memcached_multi_/ ) {
- print
-"This script needs to be named (prefix_)?memcached_multi_ to run properly.\n";
- exit 1;
-}
-
-# tell munin about our multigraph capabilities
-need_multigraph();
-
-=head1 Variable Declarations
-
- This section of code is to declare the variables used throughout the plugin
- Some of them are imported as environment variables from munin plugin conf.d
- file, others are hashes used for storing information that comes from the
- stats commands issued to memcached.
-
-=cut
-
-# lets import environment variables for the plugin or use the default
-my $host = $ENV{host} || "127.0.0.1";
-my $port = $ENV{port} || 11211;
-my $connection;
-
-# This gives us the ability to control the timescale our graphs are displaying.
-# The default it set to divide by hours, if you want to get seconds set it to 1.
-# Options: 1 = seconds, 2 = minutes, 3 = hours, 4 = days
-my $timescale = $ENV{timescale} || 3;
-
-# This gives us the ability to turn the Last Evicted Item time slab graph on.
-# It was removed because I believe the counter / response to be broken but
-# perhaps this was useful to someone.
-my $leitime = $ENV{leitime} || -1;
-
-# This gives us the ability to specify which commands we want to display on the
-# command graph. Allowing finer control since some environments don't leverage
-# every command possible in memcached.
-# Options: get set delete incr decr cas touch flush
-my $commands = $ENV{cmds} || "get set delete incr decr touch";
-
-# This hash contains the information contained in two memcache commands
-# stats and stats settings.
-my %stats;
-
-# This gives us eviction rates and other hit stats per slab
-# We track this so we can see if something was evicted earlier than necessary
-my %items;
-
-# This gives us the memory size and usage per slab
-# We track this so we can see what slab is being used the most and has no free chunks
-# so we can re-tune memcached to allocate more pages for the specified chunk size
-my %chnks;
-
-# Variable for setting up a quick access map for plugin configurations / version adherence
-my $globalmap;
-
-=head2 Graph Declarations
-
- This block of code builds up all of the graph info for all root / subgraphs.
-
- %graphs: is a container for all of the graph definition information. In here is where you'll
- find the configuration information for munin's graphing procedure.
- Format:
-
- $graph{graph_name} => {
- config => {
- You'll find the main graph config stored here
- { key => value },
- { ... },
- },
- datasrc => [
- Name: name given to data value
- Attr: Attribute and value, attribute must be valid plugin argument
- { name => 'Name', info => 'info about graph', ... },
- { ... },
- ],
- }
-
-=cut
-
-my %graphs;
-
-# main graph for memcached item count
-$graphs{items} = {
- config => {
- args => '--base 1000 --lower-limit 0',
- vlabel => 'Items in Memcached',
- category => 'memcached global items',
- title => 'Items',
- info => 'Number of items in use by memcached',
- },
- datasrc => [
- { name => 'curr_items', label => 'Current Items', min => '0' },
- {
- name => 'total_items',
- label => 'New Items',
- min => '0',
- type => 'DERIVE'
- },
- ],
-};
-
-# main graph for memcached memory usage
-$graphs{memory} = {
- config => {
- args => '--base 1024 --lower-limit 0',
- vlabel => 'Bytes Used',
- category => 'memcached global memory',
- title => 'Memory Usage',
- info => 'Memory consumption of memcached',
- },
- datasrc => [
- {
- name => 'limit_maxbytes',
- draw => 'AREA',
- label => 'Maximum Bytes Allocated',
- min => '0'
- },
- {
- name => 'bytes',
- draw => 'AREA',
- label => 'Current Bytes Used',
- min => '0'
- },
- ],
-};
-
-# main graph for memcached network usage
-$graphs{bytes} = {
- config => {
- args => '--base 1000',
- vlabel => 'bits in (-) / out (+)',
- title => 'Network Traffic',
- category => 'memcached',
- info => 'Network traffic in (-) / out (+) of the machine',
- order => 'bytes_read bytes_written',
- },
- datasrc => [
- {
- name => 'bytes_read',
- type => 'DERIVE',
- label => 'Network Traffic coming in (-)',
- graph => 'no',
- cdef => 'bytes_read,8,*',
- min => '0'
- },
- {
- name => 'bytes_written',
- type => 'DERIVE',
- label => 'Traffic in (-) / out (+)',
- negative => 'bytes_read',
- cdef => 'bytes_written,8,*',
- min => '0'
- },
- ],
-};
-
-# graph for memcached connections
-$graphs{conns} = {
- config => {
- args => '--base 1000 --lower-limit 0',
- vlabel => 'Connections per ${graph_period}',
- category => 'memcached',
- title => 'Connections',
- info => 'Number of connections being handled by memcached',
- order => 'max_conns curr_conns avg_conns',
- },
- datasrc => [
- { name => 'curr_conns', label => 'Current Connections', min => '0' },
- { name => 'max_conns', label => 'Max Connections', min => '0' },
- { name => 'avg_conns', label => 'Avg Connections', min => '0' },
- ],
-};
-
-# main graph for memcached commands issued
-$graphs{commands} = {
- config => {
- args => '--base 1000 --lower-limit 0',
- vlabel => 'Commands per ${graph_period}',
- category => 'memcached global commands',
- title => 'Commands',
- info => 'Number of commands being handled by memcached',
- },
- datasrc => [
- {
- name => 'cmd_get',
- type => 'DERIVE',
- label => 'Gets',
- info => 'Cumulative number of retrieval reqs',
- min => '0'
- },
- {
- name => 'cmd_set',
- type => 'DERIVE',
- label => 'Sets',
- info => 'Cumulative number of storage reqs',
- min => '0'
- },
- {
- name => 'cmd_flush',
- type => 'DERIVE',
- label => 'Flushes',
- info => 'Cumulative number of flush reqs',
- min => '0'
- },
- {
- name => 'cmd_touch',
- type => 'DERIVE',
- label => 'Touches',
- info => 'Cumulative number of touch reqs',
- min => '0'
- },
- {
- name => 'get_hits',
- type => 'DERIVE',
- label => 'Get Hits',
- info => 'Number of keys that were requested and found',
- min => '0'
- },
- {
- name => 'get_misses',
- type => 'DERIVE',
- label => 'Get Misses',
- info => 'Number of keys there were requested and not found',
- min => '0'
- },
- {
- name => 'delete_hits',
- type => 'DERIVE',
- label => 'Delete Hits',
- info =>
- 'Number of delete requests that resulted in a deletion of a key',
- min => '0'
- },
- {
- name => 'delete_misses',
- type => 'DERIVE',
- label => 'Delete Misses',
- info => 'Number of delete requests for missing key',
- min => '0'
- },
- {
- name => 'incr_hits',
- type => 'DERIVE',
- label => 'Increment Hits',
- info => 'Number of successful increment requests',
- min => '0'
- },
- {
- name => 'incr_misses',
- type => 'DERIVE',
- label => 'Increment Misses',
- info => 'Number of unsuccessful increment requests',
- min => '0'
- },
- {
- name => 'decr_hits',
- type => 'DERIVE',
- label => 'Decrement Hits',
- info => 'Number of successful decrement requests',
- min => '0'
- },
- {
- name => 'decr_misses',
- type => 'DERIVE',
- label => 'Decrement Misses',
- info => 'Number of unsuccessful decrement requests',
- min => '0'
- },
- {
- name => 'cas_misses',
- type => 'DERIVE',
- label => 'CAS Misses',
- info => 'Number of Compare and Swap requests against missing keys',
- min => '0'
- },
- {
- name => 'cas_hits',
- type => 'DERIVE',
- label => 'CAS Hits',
- info => 'Number of successful Compare and Swap requests',
- min => '0'
- },
- {
- name => 'cas_badval',
- type => 'DERIVE',
- label => 'CAS Badval',
- info => 'Number of unsuccessful Compare and Swap requests',
- min => '0'
- },
- {
- name => 'touch_hits',
- type => 'DERIVE',
- label => 'Touch Hits',
- info => 'Number of successfully touched keys',
- min => '0'
- },
- {
- name => 'touch_misses',
- type => 'DERIVE',
- label => 'Touch Misses',
- info => 'Number of unsuccessful touch keys',
- min => '0'
- },
- ],
-};
-
-# main graph for memcached eviction rates
-$graphs{evictions} = {
- config => {
- args => '--base 1000 --lower-limit 0',
- vlabel => 'Evictions per ${graph_period}',
- category => 'memcached global evictions',
- title => 'Evictions',
- info => 'Number of evictions per second',
- },
- datasrc => [
- {
- name => 'evictions',
- type => 'DERIVE',
- label => 'Evictions',
- info => 'Cumulative Evictions Across All Slabs',
- min => '0'
- },
- {
- name => 'evicted_nonzero',
- type => 'DERIVE',
- label => 'Evictions prior to Expire',
- info => 'Cumulative Evictions forced to expire prior to expiration',
- min => '0'
- },
- {
- name => 'reclaimed',
- type => 'DERIVE',
- label => 'Reclaimed Items',
- info => 'Cumulative Reclaimed Item Entries Across All Slabs',
- min => '0'
- },
- ],
-};
-
-# main graph for memcached eviction rates
-$graphs{unfetched} = {
- config => {
- args => '--base 1000 --lower-limit 0',
- vlabel => 'Unfetched Items per ${graph_period}',
- category => 'memcached global unfetched',
- title => 'Unfetched Items',
- info =>
-'Number of items that were never touched get/incr/append/etc before X occured',
- },
- datasrc => [
- {
- name => 'expired_unfetched',
- type => 'DERIVE',
- label => 'Expired Unfetched',
- min => '0',
- info =>
-'Number of items that expired and never had get/incr/append/etc performed'
- },
- {
- name => 'evicted_unfetched',
- type => 'DERIVE',
- label => 'Evictioned Unfetched',
- min => '0',
- info =>
-'Number of items that evicted and never had get/incr/append/etc performed'
- },
- ],
-};
-
-# subgraph for breaking memory info down by slab ( subgraph of memory )
-$graphs{slabchnks} = {
- config => {
- args => '--base 1000 --lower-limit 0',
- vlabel => 'Available Chunks for this Slab',
- category => 'memcached slab chunk usage',
- title => 'Chunk Usage for Slab: ',
- info => 'This graph shows you the chunk usage for this memory slab.',
- },
- datasrc => [
- {
- name => 'total_chunks',
- label => 'Total Chunks Available',
- min => '0'
- },
- { name => 'used_chunks', label => 'Total Chunks in Use', min => '0' },
- {
- name => 'free_chunks',
- label => 'Total Chunks Not in Use (Free)',
- min => '0'
- },
- ],
-};
-
-# subgraph for breaking commands down by slab ( subgraph of commands )
-$graphs{slabhits} = {
- config => {
- args => '--base 1000 --lower-limit 0',
- vlabel => 'Hits per Slab per ${graph_period}',
- category => 'memcached slab commands',
- title => 'Hits for Slab: ',
- info =>
- 'This graph shows you the successful hit rate for this memory slab.',
- },
- datasrc => [
- {
- name => 'get_hits',
- label => 'Get Requests',
- type => 'DERIVE',
- min => '0'
- },
- {
- name => 'cmd_set',
- label => 'Set Requests',
- type => 'DERIVE',
- min => '0'
- },
- {
- name => 'delete_hits',
- label => 'Delete Requests',
- type => 'DERIVE',
- min => '0'
- },
- {
- name => 'incr_hits',
- label => 'Increment Requests',
- type => 'DERIVE',
- min => '0'
- },
- {
- name => 'decr_hits',
- label => 'Decrement Requests',
- type => 'DERIVE',
- min => '0'
- },
- {
- name => 'cas_hits',
- label => 'Sucessful CAS Requests',
- type => 'DERIVE',
- min => '0'
- },
- {
- name => 'cas_badval',
- label => 'UnSucessful CAS Requests',
- type => 'DERIVE',
- min => '0'
- },
- {
- name => 'touch_hits',
- label => 'Touch Requests',
- type => 'DERIVE',
- min => '0'
- },
- ],
-};
-
-# subgraph for breaking evictions down by slab ( subgraph of evictions )
-$graphs{slabevics} = {
- config => {
- args => '--base 1000 --lower-limit 0',
- vlabel => 'Evictions per Slab per ${graph_period}',
- category => 'memcached slab evictions',
- title => 'Evictions for Slab: ',
- info => 'This graph shows you the eviction rate for this memory slab.',
- },
- datasrc => [
- {
- name => 'evicted',
- label => 'Total Evictions',
- type => 'DERIVE',
- min => '0',
- info => 'Items evicted from memory slab'
- },
- {
- name => 'evicted_nonzero',
- type => 'DERIVE',
- label => 'Evictions from LRU Prior to Expire',
- info => 'Items evicted from memory slab before ttl expiration',
- min => '0'
- },
- {
- name => 'reclaimed',
- type => 'DERIVE',
- label => 'Reclaimed Expired Items',
- info =>
- 'Number of times an item was stored in expired memory slab space',
- min => '0'
- },
- ],
-};
-
-# subgraph for showing the time between an item was last evicted and requested ( subgraph of evictions )
-$graphs{slabevictime} = {
- config => {
- args => '--base 1000 --lower-limit 0',
- vlabel => ' since Request for LEI',
- category => 'memcached slab eviction time',
- title => 'Eviction Request Time for Slab: ',
- info =>
-'This graph shows you the time since we requested the last evicted item',
- },
- datasrc => [
- {
- name => 'evicted_time',
- label => 'Eviction Time (LEI)',
- info => 'Time Since Request for Last Evicted Item',
- min => '0'
- },
- ],
-};
-
-# subgraph for breaking items down by slab ( subgraph of items )
-$graphs{slabitems} = {
- config => {
- args => '--base 1000 --lower-limit 0',
- vlabel => 'Items per Slab',
- category => 'memcached slab item count',
- title => 'Items in Slab: ',
- info =>
-'This graph shows you the number of items and reclaimed items per slab.',
- },
- datasrc => [
- {
- name => 'number',
- label => 'Items',
- draw => 'AREA',
- info => 'This is the amount of items stored in this slab',
- min => '0'
- },
- ],
-};
-
-# subgraph for showing the age of the eldest item stored in a slab ( subgraph of items )
-$graphs{slabitemtime} = {
- config => {
- args => '--base 1000 --lower-limit 0',
- vlabel => ' since item was stored',
- category => 'memcached slab item age',
- title => 'Age of Eldest Item in Slab: ',
- info => 'This graph shows you the time of the eldest item in this slab',
- },
- datasrc =>
- [ { name => 'age', label => 'Eldest Item\'s Age', min => '0' }, ],
-};
-
-# main graph for memcached eviction rates
-$graphs{slabunfetched} = {
- config => {
- args => '--base 1000 --lower-limit 0',
- vlabel => 'Unfetched Items per ${graph_period}',
- category => 'memcached slab unfetched',
- title => 'Unfetched Items in Slab: ',
- info =>
-'Number of items that were never touched get/incr/append/etc before X occured',
- },
- datasrc => [
- {
- name => 'expired_unfetched',
- type => 'DERIVE',
- label => 'Expired Unfetched',
- min => '0',
- info =>
-'Number of items that expired and never had get/incr/append/etc performed'
- },
- {
- name => 'evicted_unfetched',
- type => 'DERIVE',
- label => 'Evictioned Unfetched',
- min => '0',
- info =>
-'Number of items that evicted and never had get/incr/append/etc performed'
- },
- ],
-};
-
-=head1 Munin Checks
-
- These checks look for config / autoconf / suggest params
-
-=head2 Config Check
-
- This block of code looks at the argument that is possibly supplied,
- should it be config, it then checks to make sure the plugin
- specified exists, assuming it does, it will run the do_config
- subroutine for the plugin specified, otherwise it dies complaining
- about an unknown plugin.
-
-=cut
-
-if ( defined $ARGV[0] && $ARGV[0] eq 'config' ) {
-
-# Lets get our plugin from the symlink being called up, we'll also verify its a valid
-# plugin that we have graph information for
- $0 =~ /(?:([^\/]+)_)?memcached_multi_(.+)$/;
- my $prefix = $1 ? $1 : '';
- my $plugin = $2;
- die 'Unknown Plugin Specified: ' . ( $plugin ? $plugin : '' )
- unless $graphs{$plugin};
-
-# We need to fetch the stats before we do any config, cause its needed for multigraph
-# subgraphs which use slab information for title / info per slab
- fetch_stats();
- $globalmap = buildglobalmap();
-
- # Now lets go ahead and print out our config.
- do_config( $prefix, $plugin );
- exit 0;
-}
-
-=head2 Autoconf Check
-
- This block of code looks at the argument that is possibly supplied,
- should it be autoconf, we will attempt to connect to the memcached
- service specified on the host:port, upon successful connection it
- prints yes, otherwise it prints no.
-
-=cut
-
-if ( defined $ARGV[0] && $ARGV[0] eq 'autoconf' ) {
-
- # Lets attempt to connect to memcached
- my $s = get_conn();
-
- # Lets verify that we did connect to memcached
- if ( defined($s) ) {
- print "yes\n";
- exit 0;
- }
- else {
- print "no (unable to connect to $connection)\n";
- exit 0;
- }
-}
-
-=head2 Suggest Check
-
- This block of code looks at the argument that is possibly supplied,
- should it be suggest, we are going to print the possible plugins
- which can be specified. Note we only specify the root graphs for the
- multigraphs, since the rest of the subgraphs will appear "behind" the
- root graphs. It also attempts to connect to the memcached service to
- verify it is infact running.
-
-=cut
-
-if ( defined $ARGV[0] && $ARGV[0] eq 'suggest' ) {
-
- # Lets attempt to connect to memcached
- my $s = get_conn();
-
- # Lets check that we did connect to memcached
- if ( defined($s) ) {
- fetch_stats();
- my @rootplugins =
- ( 'bytes', 'conns', 'commands', 'evictions', 'items', 'memory' );
- if ( $stats{version} !~ /^1\.4\.[0-7]$/ ) {
- push( @rootplugins, 'unfetched' );
- }
- foreach my $plugin (@rootplugins) {
- print "$plugin\n";
- }
- exit 0;
- }
- else {
- print "no (unable to connect to $connection)\n";
- exit 0;
- }
-}
-
-=head1 Output Subroutines
-
- Output Subroutine calls to output data values
-
-=head2 fetch_output
-
- This subroutine is the main call for printing data for the plugin.
- No parameters are taken as this is the default call if no arguments
- are supplied from the command line.
-
-=cut
-
-# Well, no arguments were supplied that we know about, so lets print some data
-$0 =~ /(?:([^\/]+)_)?memcached_multi_(.+)$/;
-my $prefix = $1 ? $1 : '';
-my $plugin = $2;
-die 'Unknown Plugin Specified: ' . ( $plugin ? $plugin : '' )
- unless $graphs{$plugin};
-fetch_stats();
-$globalmap = buildglobalmap();
-fetch_output( $prefix, $plugin );
-
-sub fetch_output {
- my ( $prefix, $plugin ) = (@_);
-
- # Now lets go ahead and print out our output.
- my @subgraphs;
- if ( $plugin eq 'memory' ) {
- @subgraphs = ('slabchnks');
- foreach my $slabid ( sort { $a <=> $b } keys %chnks ) {
- print_submulti_output( $prefix, $slabid, $plugin, @subgraphs );
- }
- print_subrootmulti_output( $prefix, $plugin );
- print_rootmulti_output( $prefix, $plugin );
- }
- elsif ( $plugin eq 'commands' ) {
- @subgraphs = ('slabhits');
- foreach my $slabid ( sort { $a <=> $b } keys %chnks ) {
- print_submulti_output( $prefix, $slabid, $plugin, @subgraphs );
- }
- print_subrootmulti_output( $prefix, $plugin );
- print_rootmulti_output( $prefix, $plugin );
- }
- elsif ( $plugin eq 'evictions' ) {
- @subgraphs = ('slabevics');
- if ( $leitime == 1 ) { push( @subgraphs, 'slabevictime' ); }
- foreach my $slabid ( sort { $a <=> $b } keys %items ) {
- print_submulti_output( $prefix, $slabid, $plugin, @subgraphs );
- }
- print_subrootmulti_output( $prefix, $plugin );
- print_rootmulti_output( $prefix, $plugin );
- }
- elsif ( $plugin eq 'items' ) {
- @subgraphs = ( 'slabitems', 'slabitemtime' );
- foreach my $slabid ( sort { $a <=> $b } keys %items ) {
- print_submulti_output( $prefix, $slabid, $plugin, @subgraphs );
- }
- print_subrootmulti_output( $prefix, $plugin );
- print_rootmulti_output( $prefix, $plugin );
- }
- elsif ( $plugin eq 'unfetched' ) {
- @subgraphs = ('slabunfetched');
- foreach my $slabid ( sort { $a <=> $b } keys %items ) {
- print_submulti_output( $prefix, $slabid, $plugin, @subgraphs );
- }
- print_subrootmulti_output( $prefix, $plugin );
- print_rootmulti_output( $prefix, $plugin );
- }
- else {
- print_root_output($plugin);
- }
-
- return;
-}
-
-=head2 print_root_output
-
- This subroutine prints out the return values for our non-multigraph root graphs.
- It takes one parameter $plugin and returns when completed.
-
- $plugin; graph we are calling up to print data values for
-
- Example: print_root_output($plugin);
-
-=cut
-
-sub print_root_output {
-
- # Lets get our plugin, set our graph reference and print out info for Munin
- my ($plugin) = (@_);
- my $graph = $graphs{$plugin};
-
- # The conns plugin has some specific needs, looking for plugin type
- if ( $plugin ne 'conns' ) {
- foreach my $dsrc ( @{ $graph->{datasrc} } ) {
- my %datasrc = %$dsrc;
- while ( my ( $key, $value ) = each(%datasrc) ) {
- next if ( $key ne 'name' );
- my $output = $stats{$value};
- print "$dsrc->{name}.value $output\n";
- }
- }
- }
- else {
- my $output;
- foreach my $dsrc ( @{ $graph->{datasrc} } ) {
- my %datasrc = %$dsrc;
- while ( my ( $key, $value ) = each(%datasrc) ) {
- if ( $value eq 'max_conns' ) {
- $output = $stats{maxconns};
- }
- elsif ( $value eq 'curr_conns' ) {
- $output = $stats{curr_connections};
- }
- elsif ( $value eq 'avg_conns' ) {
- $output = sprintf( "%02d",
- $stats{total_connections} / $stats{uptime} );
- }
- else {
- next;
- }
- print "$dsrc->{name}.value $output\n";
- }
- }
- }
- return;
-}
-
-=head2 print_rootmulti_output
-
- This subroutine prints out the return values for our multigraph root graphs.
- It takes one parameter $plugin and returns when completed.
-
- $plugin; root graph we are calling up to print data values for
-
- Example: print_rootmulti_output($plugin);
-
-=cut
-
-sub print_rootmulti_output {
-
- # Lets get our plugin, set our graph reference and print out info for Munin
- my ( $prefix, $plugin ) = (@_);
- my $graph = $graphs{$plugin};
- if ($prefix) {
- print "multigraph $prefix\_memcached_multi_$plugin\n";
- }
- else {
- print "multigraph memcached_multi_$plugin\n";
- }
-
- # Lets print our data values with their appropriate name
- foreach my $dsrc ( @{ $graph->{datasrc} } ) {
- my $output = 0;
- my %datasrc = %$dsrc;
- while ( my ( $key, $value ) = each(%datasrc) ) {
- next if ( $key ne 'name' );
- next
- if ( ( $plugin eq 'evictions' )
- && ( !exists( $globalmap->{globalevics}->{ $dsrc->{name} } ) )
- );
- next
- if ( ( $plugin eq 'commands' )
- && ( !exists( $globalmap->{globalcmds}->{ $dsrc->{name} } ) ) );
- if ( ( $plugin eq 'evictions' ) && ( $value eq 'evicted_nonzero' ) )
- {
- foreach my $slabid ( sort { $a <=> $b } keys %items ) {
- $output += $items{$slabid}->{evicted_nonzero};
- }
- }
- else {
- $output = $stats{$value};
- }
- print "$dsrc->{name}.value $output\n";
- }
- }
- return;
-}
-
-=head2 print_subrootmulti_output
-
- This subroutine prints out the return values for our multigraph root graphs, only this set of
- data will display on the subpage made by the multigraph capabilities of munin and the plugin.
- It takes one parameter $plugin and returns when completed.
-
- $plugin; root graph we are calling up to print data values for
-
- Example: print_rootmulti_output($plugin);
-
-=cut
-
-sub print_subrootmulti_output {
-
- # Lets get our plugin, set our graph reference and print out info for Munin
- my ( $prefix, $plugin ) = (@_);
- my $graph = $graphs{$plugin};
- if ($prefix) {
- if ( $plugin eq 'evictions' ) {
- print "multigraph $prefix\_memcached_multi_$plugin.global$plugin\n";
- }
- else {
- print "multigraph $prefix\_memcached_multi_$plugin.$plugin\n";
- }
- }
- else {
- if ( $plugin eq 'evictions' ) {
- print "multigraph memcached_multi_$plugin.global$plugin\n";
- }
- else {
- print "multigraph memcached_multi_$plugin.$plugin\n";
- }
- }
-
- # Lets print our data values with their appropriate name
- foreach my $dsrc ( @{ $graph->{datasrc} } ) {
- my $output = 0;
- my %datasrc = %$dsrc;
- while ( my ( $key, $value ) = each(%datasrc) ) {
- next if ( $key ne 'name' );
- next
- if ( ( $plugin eq 'evictions' )
- && ( !exists( $globalmap->{globalevics}->{ $dsrc->{name} } ) )
- );
- next
- if ( ( $plugin eq 'commands' )
- && ( !exists( $globalmap->{globalcmds}->{ $dsrc->{name} } ) ) );
- if ( ( $plugin eq 'evictions' ) && ( $value eq 'evicted_nonzero' ) )
- {
- foreach my $slabid ( sort { $a <=> $b } keys %items ) {
- $output += $items{$slabid}->{evicted_nonzero};
- }
- }
- else {
- $output = $stats{$value};
- }
- print "$dsrc->{name}.value $output\n";
- }
- }
- return;
-}
-
-=head2 print_submulti_output
-
- This subroutine prints out the return values for our multigraph subgraphs. It takes
- three parameters $slabid, $plugin, @subgraphs and then rReturns when completed.
-
- $slabid; slab id that we will use to grab info from and print out
- $plugin; root graph being called, used for multigraph output and slab id
- @subgraphs; graphs we are actually trying to print data values for
-
- Example: print_submulti_output($slabid,$plugin,@subgraphs);
-
-=cut
-
-sub print_submulti_output {
-
- # Lets get our slabid, plugin, and subgraphs
- my ( $prefix, $slabid, $plugin, @subgraphs ) = (@_);
- my $currslab = undef;
-
- # Time to loop over our subgraphs array
- foreach my $sgraph (@subgraphs) {
-
- # Lets set our graph reference for quick calling, and print some info for munin
- my $graph = $graphs{$sgraph};
- if ($prefix) {
- print
- "multigraph $prefix\_memcached_multi_$plugin.$sgraph\_$slabid\n";
- }
- else {
- print "multigraph memcached_multi_$plugin.$sgraph\_$slabid\n";
- }
-
- # Lets figure out what slab info we are trying to call up
- if ( ( $plugin eq 'evictions' )
- || ( $plugin eq 'items' )
- || ( $plugin eq 'unfetched' ) )
- {
- $currslab = $items{$slabid};
- }
- elsif ( ( $plugin eq 'memory' ) || ( $plugin eq 'commands' ) ) {
- $currslab = $chnks{$slabid};
- }
- else {
- return;
- }
-
- # Lets print our data values with their appropriate name
- foreach my $dsrc ( @{ $graph->{datasrc} } ) {
- my %datasrc = %$dsrc;
- while ( my ( $key, $value ) = each(%datasrc) ) {
- next if ( $key ne 'name' );
- next
- if ( ( $sgraph eq 'slabevics' )
- && ( !exists( $globalmap->{slabevics}->{ $dsrc->{name} } ) )
- );
- next
- if ( ( $plugin eq 'commands' )
- && ( !exists( $globalmap->{slabcmds}->{ $dsrc->{name} } ) )
- );
- my $output = $currslab->{$value};
- if ( ( $sgraph eq 'slabevictime' )
- || ( $sgraph eq 'slabitemtime' ) )
- {
- $output = time_scale( 'data', $output );
- }
- print "$dsrc->{name}.value $output\n";
- }
- }
- }
- return;
-}
-
-=head1 Config Subroutines
-
- These subroutines handle the config portion of munin calls.
-
-=head2 do_config
-
- This is the main call issued assuming we call up config and plugin specified exists
- The subroutine takes one parameter $plugin, and returns when completed.
-
- $plugin; root graph being called
-
- Example: do_config($prefix, $plugin);
-
-=cut
-
-sub do_config {
- my ( $prefix, $plugin ) = (@_);
- my @subgraphs;
- if ( $plugin eq 'memory' ) {
- @subgraphs = ('slabchnks');
- foreach my $slabid ( sort { $a <=> $b } keys %chnks ) {
- print_submulti_config( $prefix, $slabid, $plugin, @subgraphs );
- }
- print_subrootmulti_config( $prefix, $plugin );
- print_rootmulti_config( $prefix, $plugin );
- }
- elsif ( $plugin eq 'commands' ) {
- @subgraphs = ('slabhits');
- foreach my $slabid ( sort { $a <=> $b } keys %chnks ) {
- print_submulti_config( $prefix, $slabid, $plugin, @subgraphs );
- }
- print_subrootmulti_config( $prefix, $plugin );
- print_rootmulti_config( $prefix, $plugin );
- }
- elsif ( $plugin eq 'evictions' ) {
- @subgraphs = ('slabevics');
- if ( $leitime == 1 ) { push( @subgraphs, 'slabevictime' ); }
- foreach my $slabid ( sort { $a <=> $b } keys %items ) {
- print_submulti_config( $prefix, $slabid, $plugin, @subgraphs );
- }
- print_subrootmulti_config( $prefix, $plugin );
- print_rootmulti_config( $prefix, $plugin );
- }
- elsif ( $plugin eq 'items' ) {
- @subgraphs = ( 'slabitems', 'slabitemtime' );
- foreach my $slabid ( sort { $a <=> $b } keys %items ) {
- print_submulti_config( $prefix, $slabid, $plugin, @subgraphs );
- }
- print_subrootmulti_config( $prefix, $plugin );
- print_rootmulti_config( $prefix, $plugin );
- }
- elsif ( $plugin eq 'unfetched' ) {
- @subgraphs = ('slabunfetched');
- foreach my $slabid ( sort { $a <=> $b } keys %items ) {
- print_submulti_config( $prefix, $slabid, $plugin, @subgraphs );
- }
- print_subrootmulti_config( $prefix, $plugin );
- print_rootmulti_config( $prefix, $plugin );
- }
- else {
- print_root_config( $prefix, $plugin );
- }
-
- return;
-}
-
-=head2 print_root_config
-
- This subroutine prints out the config information for all of the non-multigraph root graphs.
- It takes one parameter, $plugin, returns when completed.
-
- $prefix; possible prefix used to allow multiple plugins per machine
- $plugin; root graph used for multigraph call
-
- Example: print_root_config($prefix,$plugin);
-
-=cut
-
-sub print_root_config {
-
- # Lets get our plugin, set our graph reference and our graph config info
- my ( $prefix, $plugin ) = (@_);
- my $graph = $graphs{$plugin};
- my %graphconf = %{ $graph->{config} };
-
- # Lets tell munin about the graph we are referencing and print the main config
- while ( my ( $key, $value ) = each(%graphconf) ) {
- if ( $key eq 'title' ) {
- if ($prefix) {
- print "graph_$key " . ucfirst($prefix) . " $value\n";
- }
- else {
- print "graph_$key $value\n";
- }
- }
- else {
- print "graph_$key $value\n";
- }
- }
-
- # Lets tell munin about our data values and how to treat them
- foreach my $dsrc ( @{ $graph->{datasrc} } ) {
- my %datasrc = %$dsrc;
- while ( my ( $key, $value ) = each(%datasrc) ) {
- next if ( $key eq 'name' );
- print "$dsrc->{name}.$key $value\n";
- }
- }
- return;
-}
-
-=head2 print_rootmulti_config
-
- This subroutine prints out the config information for all of the multigraph root graphs.
- It takes one parameter, $plugin, returns when completed.
-
- $prefix; possible prefix used to allow multiple plugins per machine
- $plugin; root graph used for multigraph call
-
- Example: print_rootmulti_config($prefix,$plugin);
-
-=cut
-
-sub print_rootmulti_config {
-
- # Lets get out plugin, set our graph reference and our graph config info
- my ( $prefix, $plugin ) = (@_);
- my $graph = $graphs{$plugin};
- my %graphconf = %{ $graph->{config} };
-
- # Lets tell munin about the graph we are referencing and print the main config
- if ($prefix) {
- print "multigraph $prefix\_memcached_multi_$plugin\n";
- }
- else {
- print "multigraph memcached_multi_$plugin\n";
- }
- while ( my ( $key, $value ) = each(%graphconf) ) {
- if ( $key eq 'category' ) {
- print "graph_$key memcached\n";
- }
- elsif ( $key eq 'title' ) {
- if ($prefix) {
- print "graph_$key " . ucfirst($prefix) . " $value\n";
- }
- else {
- print "graph_$key $value\n";
- }
- }
- else {
- print "graph_$key $value\n";
- }
- }
-
- # Lets tell munin about our data values and how to treat them
- foreach my $dsrc ( @{ $graph->{datasrc} } ) {
- my %datasrc = %$dsrc;
- while ( my ( $key, $value ) = each(%datasrc) ) {
- next if ( $key eq 'name' );
- next
- if ( ( $plugin eq 'evictions' )
- && ( !exists( $globalmap->{globalevics}->{ $dsrc->{name} } ) )
- );
- next
- if ( ( $plugin eq 'commands' )
- && ( !exists( $globalmap->{globalcmds}->{ $dsrc->{name} } ) ) );
- print "$dsrc->{name}.$key $value\n";
- }
- }
- return;
-}
-
-=head2 print_subrootmulti_config
-
- This subroutine prints out the config information for all of the multigraph root graph, only this
- graph of the data will display on the subpage made by the multigraph capabilities of munin and
- the plugin. It takes one parameter, $plugin, returns when completed.
-
- $prefix; possible prefix used to allow multiple plugins per machine
- $plugin; root graph used for multigraph call
-
- Example: print_rootmulti_config($prefix,$plugin);
-
-=cut
-
-sub print_subrootmulti_config {
-
- # Lets get out plugin, set our graph reference and our graph config info
- my ( $prefix, $plugin ) = (@_);
- my $graph = $graphs{$plugin};
- my %graphconf = %{ $graph->{config} };
- if ($prefix) {
- if ( $plugin eq 'evictions' ) {
- print "multigraph $prefix\_memcached_multi_$plugin.global$plugin\n";
- }
- else {
- print "multigraph $prefix\_memcached_multi_$plugin.$plugin\n";
- }
- }
- else {
- if ( $plugin eq 'evictions' ) {
- print "multigraph memcached_multi_$plugin.global$plugin\n";
- }
- else {
- print "multigraph memcached_multi_$plugin.$plugin\n";
- }
- }
-
- while ( my ( $key, $value ) = each(%graphconf) ) {
- if ( $key eq 'title' ) {
- if ($prefix) {
- print "graph_$key " . ucfirst($prefix) . " $value\n";
- }
- else {
- print "graph_$key $value\n";
- }
- }
- else {
- print "graph_$key $value\n";
- }
- }
-
- # Lets tell munin about our data values and how to treat them
- foreach my $dsrc ( @{ $graph->{datasrc} } ) {
- my %datasrc = %$dsrc;
- while ( my ( $key, $value ) = each(%datasrc) ) {
- next if ( $key eq 'name' );
- next
- if ( ( $plugin eq 'evictions' )
- && ( !exists( $globalmap->{globalevics}->{ $dsrc->{name} } ) )
- );
- next
- if ( ( $plugin eq 'commands' )
- && ( !exists( $globalmap->{globalcmds}->{ $dsrc->{name} } ) ) );
- print "$dsrc->{name}.$key $value\n";
- }
- }
- return;
-}
-
-=head2 print_submulti_config
-
- This subroutine prints out the config information for all of the multigraph subgraphs.
- It takes three parameters, $slabid, $plugin and @subgraphs, returns when completed.
-
- $prefix; possible prefix used to allow multiple plugins per machine
- $slabid; slab id that we will use to grab info from and print out
- $plugin; root graph being called, used for multigraph output and slab id
- @subgraphs; graphs we are actually trying to print data values for
-
- Example: print_submulti_config($prefix,$slabid,$plugin,@subgraphs);
-
-=cut
-
-sub print_submulti_config {
-
- # Lets get our slabid, plugin, and subgraphs
- my ( $prefix, $slabid, $plugin, @subgraphs ) = (@_);
- my ( $slabitems, $slabchnks ) = undef;
-
- # Time to loop over our subgraphs array
- foreach my $sgraph (@subgraphs) {
-
- # Lets set our graph reference, and main graph config for easy handling
- my $graph = $graphs{$sgraph};
- my %graphconf = %{ $graph->{config} };
-
-# Lets tell munin which graph we are graphing, and what our main graph config info is
- if ($prefix) {
- print
- "multigraph $prefix\_memcached_multi_$plugin.$sgraph\_$slabid\n";
- }
- else {
- print "multigraph memcached_multi_$plugin.$sgraph\_$slabid\n";
- }
- while ( my ( $key, $value ) = each(%graphconf) ) {
- if ( $key eq 'title' ) {
- if ($prefix) {
- print "graph_$key "
- . ucfirst($prefix)
- . " $value"
- . "$slabid"
- . " ($chnks{$slabid}->{chunk_size} Bytes)\n";
- }
- else {
- print "graph_$key $value"
- . "$slabid"
- . " ($chnks{$slabid}->{chunk_size} Bytes)\n";
- }
- }
- elsif (
- ( $key eq 'vlabel' )
- && ( ( $sgraph eq 'slabevictime' )
- || ( $sgraph eq 'slabitemtime' ) )
- )
- {
- $value = time_scale( 'config', $value );
- print "graph_$key $value\n";
- }
- else {
- print "graph_$key $value\n";
- }
- }
-
- # Lets tell munin about our data values and how to treat them
- foreach my $dsrc ( @{ $graph->{datasrc} } ) {
- my %datasrc = %$dsrc;
- while ( my ( $key, $value ) = each(%datasrc) ) {
- next if ( $key eq 'name' );
- next
- if ( ( $sgraph eq 'slabevics' )
- && ( !exists( $globalmap->{slabevics}->{ $dsrc->{name} } ) )
- );
- next
- if ( ( $plugin eq 'commands' )
- && ( !exists( $globalmap->{slabcmds}->{ $dsrc->{name} } ) )
- );
- print "$dsrc->{name}.$key $value\n";
- }
- }
- }
- return;
-}
-
-=head1 Misc Subroutines
-
- These subroutines are misc ones, and are referenced inside of the code. They
- should never be called up by Munin.
-
-=head2 get_conn
-
- This subroutine returns a socket connection
-
-=cut
-
-sub get_conn {
- my $s = undef;
-
- # check if we want to use sockets instead of tcp
- my ($sock) = ( $host =~ /unix:\/\/(.+)*$/ );
-
- if ($sock) {
- $connection = "unix:\/\/$sock";
- $s = IO::Socket::UNIX->new( Peer => $sock );
- }
- else {
- $connection = "$host:$port";
- $s = IO::Socket::INET->new(
- Proto => "tcp",
- PeerAddr => $host,
- PeerPort => $port,
- Timeout => 10,
- );
- }
- return $s;
-}
-
-=head2 fetch_stats
-
- This subroutine fetches the information from memcached and stores it into our
- hashes for later referencing throughout the graph. Returns when completed
-
-=cut
-
-sub fetch_stats {
-
- # Lets try and connect to memcached
- my $s = get_conn();
-
- # Die if we can't establish a connection to memcached
- die "Error: Unable to Connect to $connection\n" unless $s;
-
- # Lets print the stats command and store the info from the output
- print $s "stats\r\n";
- while ( my $line = <$s> ) {
- if ( $line =~ /STAT\s(.+?)\s((\w|\d|\S)+)/ ) {
- my ( $skey, $svalue ) = ( $1, $2 );
- $stats{$skey} = $svalue;
- }
- last if $line =~ /^END/;
- }
-
- # Lets print the stats settings command and store the info from the output
- print $s "stats settings\r\n";
- while ( my $line = <$s> ) {
- if ( $line =~ /STAT\s(.+?)\s((\w|\d|\S)+)/ ) {
- my ( $skey, $svalue ) = ( $1, $2 );
- if ( $skey eq 'evictions' ) {
- $skey = 'evictions_active';
- }
- $stats{$skey} = $svalue;
- }
- last if $line =~ /^END/;
- }
-
- # Lets print the stats slabs command and store the info from the output
- print $s "stats slabs\r\n";
- while ( my $line = <$s> ) {
- if ( $line =~ /STAT\s(\d+):(.+)\s(\d+)/ ) {
- my ( $slabid, $slabkey, $slabvalue ) = ( $1, $2, $3 );
- $chnks{$slabid}->{$slabkey} = $slabvalue;
- }
- last if $line =~ /^END/;
- }
-
- # Lets print the stats items command and store the info from the output
- print $s "stats items\r\n";
- while ( my $line = <$s> ) {
- if ( $line =~ /STAT\sitems:(\d+):(.+?)\s(\d+)/ ) {
- my ( $itemid, $itemkey, $itemvalue ) = ( $1, $2, $3 );
- $items{$itemid}->{$itemkey} = $itemvalue;
- }
- last if $line =~ /^END/;
- }
-}
-
-=head2 time_scale
-
- This subroutine is here for me to adjust the timescale of the time graphs
- for last evicted item and age of eldest item in cache.
-
- Please note, after long usage I have noticed these counters may not
- be accurate, I believe the developers are aware and have submitted
- a patch upstream.
-
-=cut
-
-sub time_scale {
-
- # Lets get our config option and value to adjust
- my ( $configopt, $origvalue ) = (@_);
- my $value;
-
- # If config is defined, it returns the config info for time scale
- # If data is defined, it returns the original value after its been adjusted
- if ( $configopt eq 'config' ) {
- if ( $timescale == 1 ) {
- $value = "Seconds" . $origvalue;
- }
- elsif ( $timescale == 2 ) {
- $value = "Minutes" . $origvalue;
- }
- elsif (( $timescale == 3 )
- || ( $timescale > 4 )
- || ( !defined($timescale) ) )
- {
- $value = "Hours" . $origvalue;
- }
- elsif ( $timescale == 4 ) {
- $value = "Days" . $origvalue;
- }
- }
- elsif ( $configopt eq 'data' ) {
- if ( $timescale == 1 ) {
- $value = sprintf( "%02.2f", $origvalue / 1 );
- }
- elsif ( $timescale == 2 ) {
- $value = sprintf( "%02.2f", $origvalue / 60 );
- }
- elsif (( $timescale == 3 )
- || ( $timescale > 4 )
- || ( !defined($timescale) ) )
- {
- $value = sprintf( "%02.2f", $origvalue / 3600 );
- }
- elsif ( $timescale == 4 ) {
- $value = sprintf( "%02.2f", $origvalue / 86400 );
- }
- }
- else {
- die "Unknown time_scale option given: either [config/data]\n";
- }
- return $value;
-}
-
-=head2 buildglobalmap
-
- This subroutine looks at the specified commands inputted, and generates
- a hashref containing two arrays, one for global command keys and one for
- slab command keys.
-
-=cut
-
-sub buildglobalmap {
- my $results;
- my @cmds = split( ' ', $commands );
- foreach my $cmd (@cmds) {
- if ( $cmd eq "get" ) {
- $results->{globalcmds}->{cmd_get} = 1;
- $results->{globalcmds}->{get_hits} = 1;
- $results->{globalcmds}->{get_misses} = 1;
- $results->{slabcmds}->{get_hits} = 1;
- }
- elsif ( $cmd eq "set" ) {
- $results->{globalcmds}->{cmd_set} = 1;
- $results->{slabcmds}->{cmd_set} = 1;
- }
- elsif ( $cmd eq "delete" ) {
- $results->{globalcmds}->{delete_hits} = 1;
- $results->{globalcmds}->{delete_misses} = 1;
- $results->{slabcmds}->{delete_hits} = 1;
- }
- elsif ( $cmd eq "incr" ) {
- $results->{globalcmds}->{incr_hits} = 1;
- $results->{globalcmds}->{incr_misses} = 1;
- $results->{slabcmds}->{incr_hits} = 1;
- }
- elsif ( $cmd eq "decr" ) {
- $results->{globalcmds}->{decr_hits} = 1;
- $results->{globalcmds}->{decr_misses} = 1;
- $results->{slabcmds}->{decr_hits} = 1;
- }
- elsif ( $cmd eq "cas" ) {
- $results->{globalcmds}->{cas_hits} = 1;
- $results->{globalcmds}->{cas_misses} = 1;
- $results->{globalcmds}->{cas_badval} = 1;
- $results->{slabcmds}->{cas_hits} = 1;
- $results->{slabcmds}->{cas_badval} = 1;
- }
- elsif ( $cmd eq "touch" ) {
- if ( $stats{version} !~ /^1\.4\.[0-7]$/ ) {
- $results->{globalcmds}->{cmd_touch} = 1;
- $results->{globalcmds}->{touch_hits} = 1;
- $results->{globalcmds}->{touch_misses} = 1;
- $results->{slabcmds}->{touch_hits} = 1;
- }
- }
- elsif ( $cmd eq "flush" ) {
- if ( $stats{version} !~ /^1\.4\.[0-7]$/ ) {
- $results->{globalcmds}->{cmd_flush} = 1;
- }
- }
- else {
-
- # Do absolutely nothing...
- }
- }
- $results->{globalevics}->{evictions} = 1;
- $results->{globalevics}->{evicted_nonzero} = 1;
- $results->{slabevics}->{evicted} = 1;
- $results->{slabevics}->{evicted_nonzero} = 1;
- if ( $stats{version} !~ /^1\.4\.[0-2]$/ ) {
- $results->{globalevics}->{reclaimed} = 1;
- $results->{slabevics}->{reclaimed} = 1;
- }
- return $results;
-}
+++ /dev/null
-#!/usr/bin/perl -w
-# -*- cperl -*-
-
-use strict;
-use warnings;
-
-use IO::Socket::UNIX;
-
-$| = 1;
-
-my $arg = shift;
-if ($arg && $arg eq "config") {
- print "graph_title Munin rrdcached statistics\n";
- print "graph_category munin\n";
- print "QueueLength.label Queue length\n";
- print "UpdatesReceived.label UpdatesReceived\n";
- print "UpdatesReceived.type DERIVE\n";
- print "FlushesReceived.label FlushesReceived\n";
- print "FlushesReceived.type DERIVE\n";
- print "UpdatesWritten.label UpdatesWritten\n";
- print "UpdatesWritten.type DERIVE\n";
- print "DataSetsWritten.label DataSetsWritten\n";
- print "DataSetsWritten.type DERIVE\n";
- print "TreeNodesNumber.label TreeNodesNumber\n";
- print "TreeDepth.label TreeDepth\n";
- print "JournalBytes.label JournalBytes\n";
- print "JournalBytes.type DERIVE\n";
- print "JournalRotate.label JournalRotate\n";
- print "JournalRotate.type DERIVE\n";
- exit 0;
-}
-
-my $sock = new IO::Socket::UNIX(
- Type => SOCK_STREAM,
- Peer => "/var/run/rrdcached.sock",
-) or die "Cannot open socket : $!";
-
-print $sock "STATS\n";
-print $sock "QUIT\n";
-
-# skip first line
-<$sock>;
-print map { s/: /.value /; $_; } <$sock>;
-
-exit 0;
+++ /dev/null
-#!/usr/bin/perl
-
-=encoding utf8
-
-=head1 NAME
-
-mysql_ - Munin plugin to display misc MySQL server status
-
-=head1 APPLICABLE SYSTEMS
-
-Any MySQL platform, tested by the authors on:
-* MySQL 5.6.12
-* MySQL 5.5.32, 5.5.37
-* MySQL 5.1.29,
-* MySQL 5.0.51
-* MariaDB 5.5.39
-* MariaDB-5.5.39(galera).
-
-Plugins:
-* MariaDB-10 Query Response Time: https://mariadb.com/kb/en/mariadb/query_response_time-plugin/
-
-Information Schema tables:
-* User statistics - MariaDB-5.2+, OurDelta, Percona Server - https://mariadb.com/kb/en/mariadb/user-statistics
-
-=head1 CONFIGURATION
-
-This script is used to generate data for several graphs. To generate
-data for one specific graph, you need to create a symbolic link with a
-name like mysql_<GRAPH> to this script.
-
-If you need to run against multiple MySQL instances on the same host,
-create your symlinks with names like mysql<N>_<GRAPH> where N is any
-non-negative integer. You must also set the env.cachenamespace variable
-to a unique value for each group of symlinks.
-
-To get a list of symlinks that can be created, run:
-
- ./mysql_ suggest
-
-In addition you might need to specify connection parameters in the
-plugin configuration to override the defaults. These are the defaults:
-
- [mysql_*]
- env.mysqlconnection DBI:mysql:information_schema
- env.mysqluser root
-
-Non-default example:
-
- [mysql_*]
- env.mysqlconnection DBI:mysql:information_schema;host=127.0.0.1;port=3306
- env.mysqluser munin
- env.mysqlpassword geheim
- env.cachenamespace munin_mysql_pri
- [mysql2_*]
- env.mysqlconnection DBI:mysql:information_schema;host=127.0.0.1;port=13306
- env.mysqluser munin;
- env.mysqlpassword ryuWyawEv
- env.cachenamespace munin_mysql_alt
- [mysql10_*]
- user munin
- env.mysqluser munin
- env.mysqlconnection DBI:mysql:information_schema;mysql_read_default_file=/etc/munin/.my-10.cnf
- env.cachenamespace munin_mysql_10
- # here the [client] section of /etc/munin/.my-10.cnf is read. socket= can
- # be specified here.
-
-Creating a munin user:
-
- CREATE USER 'munin'@'localhost' IDENTIFIED BY 'ryuWyawEv';
-
-or with a unix_socket plugin (INSTALL PLUGIN unix_socket SONAME 'auth_socket')
-
- CREATE USER 'munin'@'localhost' IDENTIFIED WITH unix_socket;
-
-Note: requires 'user munin' in the configuration.
-
-The minimum required priviledges of the munin database user is:
-
- GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'munin'@'localhost';
-
-
-Warning and critical values can be set via the environment in the usual way.
-For example:
-
- [mysql_replication]
- env.slave_io_running_warning 0.5
- env.slave_sql_running_warning 0.5
- env.seconds_behind_master_warning 300
- env.seconds_behind_master_critical 600
-
-=head1 DEPENDENCIES
-
-=over
-
-=item Cache::Cache
-
-The plugin uses shared memory to cache the statistics gathered from
-MySQL. This ensures minimal inpact on the MySQL server.
-
-=item DBD::mysql
-
-=back
-
-=head1 INTERPRETATION
-
-=head2 InnoDB
-
-The statistics from innodb are mainly collected from the command
-
- SHOW ENGINE INNODB STATUS
-
-A nice walk through is found at
-L<http://www.mysqlperformanceblog.com/2006/07/17/show-innodb-status-walk-through/>
-
-Undo logs:
-L<http://blog.jcole.us/2014/04/16/the-basics-of-the-innodb-undo-logging-and-history-system/>
-
-=head2 The graphs
-
-FIX point to relevant sections in the MySQL manual and other www
-resources for each graph
-
-=over
-
-=item mysql_replication
-
-slave_io_running and slave_sql_running both translate the "Yes" values to 0 and
-anything else to 1 for their respective fields in the "SHOW SLAVE STATUS" output.
-This can be used to warn on slave failure if the warning and critical values
-are set as seen in a previous section.
-
-=item wsrep_cluster_status
-
-"Primary" is translated 0 and "non-Primary" to 1.
-
-=back
-
-=head1 LICENSE
-
-Copyright (C) 2008,2009 Kjell-Magne Øierud, 2014 Open Query
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; version 2 dated June, 1991.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-=head1 VERSION
-
-git-master + a few munin modifications
-
-This plugin was downloaded from L<http://github.com/kjellm/munin-mysql/>
-
-=head1 MAGICK MARKERS
-
- #%# family=auto
- #%# capabilities=suggest autoconf
-
-=cut
-
-use warnings;
-use strict;
-use utf8;
-
-use DBI;
-use File::Basename;
-use Math::BigInt; # Used to append "=> lib 'GMP'" here, but GMP caused
- # segfault on some occasions. Removed as I don't
- # think the tiny performance boost is worth the
- # debugging effort.
-use Storable qw(nfreeze thaw);
-
-use Munin::Plugin;
-
-my $has_cache;
-
-BEGIN {
- eval 'require Cache::SharedMemoryCache';
- $has_cache = $@ ? 0 : 1;
-}
-
-
-#---------------------------------------------------------------------
-# C O N F I G
-#---------------------------------------------------------------------
-
-my %config = (
- 'dsn' => $ENV{'mysqlconnection'} || 'DBI:mysql:information_schema',
- 'user' => $ENV{'mysqluser'} || 'root',
- 'password' => $ENV{'mysqlpassword'} || '',
- 'cache_namespace' => $ENV{'cachenamespace'} || 'munin_mysql',
-);
-
-
-#---------------------------------------------------------------------
-# C A C H E
-#---------------------------------------------------------------------
-
-my %cache_options = (
- 'namespace' => $config{cache_namespace},
- 'default_expires_in' => 60,
-);
-
-my $shared_memory_cache ;
-if ($has_cache)
-{
- $shared_memory_cache = Cache::SharedMemoryCache->new(\%cache_options)
- or die("Couldn't instantiate SharedMemoryCache");
-}
-
-#---------------------------------------------------------------------
-# G R A P H D E F I N I T I O N S
-#---------------------------------------------------------------------
-
-# These are defaults to save typing in the graph definitions
-my %defaults = (
- global_attrs => {
- args => '--base 1000',
- },
- data_source_attrs => {
- min => '0',
- type => 'DERIVE',
- draw => 'AREASTACK',
- },
-);
-
-# %graphs contains the graph definitions, it is indexed on the graph
-# name. The information stored for each graph is used for both showing
-# data source values and for printing the graph configuration. Each
-# graph follows the followingformat:
-#
-# $graph{NAME} => {
-# config => {
-# # The global attributes for this graph
-# global_attrs => {}
-# # Attributes common to all data sources in this graph
-# data_source_attrs => {}
-# },
-# data_sources => [
-# # NAME - The name of the data source (e.g. variable names
-# # from SHOW STATUS)
-# # DATA_SOURCE_ATTRS - key-value pairs with data source
-# # attributes
-# {name => 'NAME', (DATA_SOURCE_ATTRS)},
-# {...},
-# ],
-my %graphs = ();
-
-#---------------------------------------------------------------------
-
-
-$graphs{wsrep_cluster_status} = {
- config => {
- global_attrs => {
- title => 'Galera Status',
- vlabel => 'PRIMARY',
- },
- data_source_attrs => {
- draw => 'LINE1',
- min => '0',
- max => '1',
- },
- },
- data_sources => [
- {name => 'wsrep_cluster_status', label => '0-Primary, 1-Non-Primary',
- info => 'If the host is primary',
- type => 'GAUGE',
- critical => '1'},
- ],
-};
-
-$graphs{wsrep_cluster_size} = {
- config => {
- global_attrs => {
- title => 'Galera cluster size',
- vlabel => 'Hosts',
- },
- data_source_attrs => {
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'wsrep_cluster_size', label => 'Cluster size',
- info => 'The number of hosts in the cluster.',
- type => 'GAUGE'},
- ],
-};
-
-
-# http://www.codership.com/wiki/doku.php?id=galera_node_fsm
-$graphs{wsrep_local_state} = {
- config => {
- global_attrs => {
- title => 'Galera node state',
- vlabel => 'State (galera_node_fsm)',
- args => '--lower-limit 0 --upper-limit 6',
- },
- data_source_attrs => {
- draw => 'LINE1',
- min => '0',
- max => '6',
- },
- },
- data_sources => [
- {name => 'wsrep_local_state', label => '1-Joining, 2-Donor, 3-Joined, 4-Synced, 5-Donor, 6-Join after Donor ',
- info => 'The state of the node in the cluster.',
- type => 'GAUGE',
- warning => '3.5:4.5'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{wsrep_transactions} = {
- config => {
- global_attrs => {
- title => 'Galera transactions',
- },
- data_source_attrs => {
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'wsrep_last_committed', label => 'Committed transactions',
- info => '# of committed transactions.',
- type => 'COUNTER',
- min => 0},
- {name => 'wsrep_local_commits', label => 'Locally Committed transactions',
- info => '# of locally committed transactions.',
- type => 'COUNTER',
- min => 0},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{wsrep_writesets} = {
- config => {
- global_attrs => {
- title => 'Galera writesets',
- },
- data_source_attrs => {
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'wsrep_replicated', label => 'Writesets sent',
- info => '# of writesets sent to other nodes',
- type => 'COUNTER',
- min => '0',
- graph => 'no'},
- {name => 'wsrep_received', label => 'Writesets received',
- info => '# of writesets received from other nodes',
- type => 'COUNTER',
- min => '0',
- negative => 'wsrep_replicated'},
- ],
-};
-
-#-------------------------
-
-
-$graphs{wsrep_writesetbytes} = {
- config => {
- global_attrs => {
- title => 'Galera writesets bytes/sec',
- },
- data_source_attrs => {
- },
- },
- data_sources => [
- {name => 'wsrep_received_bytes', label => 'Writesets bytes received',
- info => '# of bytes in writesets received from other nodes',
- type => 'DERIVE',
- min => 0,
- graph => 'no'},
- {name => 'wsrep_replicated_bytes', label => 'Writesets bytes sent',
- info => '# of bytes in writesets sent to other nodes',
- type => 'DERIVE',
- draw => 'LINE1',
- min => 0,
- negative => 'wsrep_received_bytes'},
- {name => 'wsrep_repl_keys_bytes', label => 'Writeset key size sent',
- info => '# of bytes in writesets of keys sent to other nodes',
- type => 'DERIVE',
- min => 0},
- {name => 'wsrep_repl_data_bytes', label => 'Writeset data size sent',
- info => '# of bytes in writesets of data sent to other nodes',
- type => 'DERIVE',
- min => 0},
- {name => 'wsrep_repl_other_bytes', label => 'Writeset other size sent',
- info => '# of bytes in writesets of other data sent to other nodes',
- type => 'DERIVE',
- min => 0},
- ],
-};
-
-
-#-------------------------
-
-$graphs{wsrep_errors} = {
- config => {
- global_attrs => {
- title => 'Galera transaction problems'
- },
- data_source_attrs => {
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'wsrep_local_cert_failures', label => 'Certification failures',
- type => 'DERIVE',
- min => 0},
- {name => 'wsrep_local_bf_aborts', label => 'Aborted local transactions',
- type => 'DERIVE',
- min => 0},
- {name => 'wsrep_local_replays', label => 'Replays',
- type => 'DERIVE',
- min => 0},
- ],
-};
-
-#-------------------------
-
-$graphs{wsrep_queue} = {
- config => {
- global_attrs => {
- title => 'Galera queues',
- vlabel => 'queue length received (-) / sent (+) per ${graph_period}',
- },
- data_source_attrs => {
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'wsrep_local_recv_queue', label => 'Receive queue length',
- type => 'GAUGE',
- graph => 'no'},
- {name => 'wsrep_local_recv_queue_min', label => 'Receive queue length min',
- type => 'GAUGE',
- graph => 'no'},
- {name => 'wsrep_local_recv_queue_avg', label => 'Average receive queue length',
- type => 'GAUGE',
- graph => 'no'},
- {name => 'wsrep_local_recv_queue_max', label => 'Receive queue length max',
- type => 'GAUGE',
- graph => 'no'},
- {name => 'wsrep_local_send_queue', label => 'Send queue length',
- type => 'GAUGE',
- negative => 'wsrep_local_recv_queue'},
- {name => 'wsrep_local_send_queue_min', label => 'Send queue length min',
- type => 'GAUGE',
- negative => 'wsrep_local_recv_queue_min'},
- {name => 'wsrep_local_send_queue_avg', label => 'Average send queue length',
- type => 'GAUGE',
- negative => 'wsrep_local_recv_queue_avg'},
- {name => 'wsrep_local_send_queue_max', label => 'Send queue length max',
- type => 'GAUGE',
- negative => 'wsrep_local_recv_queue_max'},
- ],
-};
-
-#-------------------------
-
-$graphs{wsrep_concurrency} = {
- config => {
- global_attrs => {
- title => 'Galera Performance - Apply to Commit',
- vlabel => 'commit + / apply - '
- },
- data_source_attrs => {
- draw => 'LINE1',
- type => 'GAUGE',
- },
- },
- data_sources => [
- {name => 'wsrep_apply_window', label => 'apply window',
- graph => 'no'},
- {name => 'wsrep_apply_oooe', label => 'apply out of order',
- graph => 'no'},
- {name => 'wsrep_apply_oool', label => 'apply out of order (slowness)',
- graph => 'no'},
- {name => 'wsrep_commit_window', label => 'commit window',
- negative => 'wsrep_apply_window'},
- {name => 'wsrep_commit_oooe', label => 'commit out of order',
- negative => 'wsrep_apply_oooe'},
- {name => 'wsrep_commit_oool', label => 'commit out of order (slowness)',
- negative => 'wsrep_apply_oool'},
- ],
-};
-
-#-------------------------
-
-$graphs{wsrep_flow} = {
- config => {
- global_attrs => {
- title => 'Galera flow control',
- vlabel => 'events received (-) / sent (+) per ${graph_period}',
- },
- data_source_attrs => {
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'wsrep_flow_control_recv', label => 'Pause events received',
- type => 'DERIVE',
- min => 0,
- graph => 'no'},
- {name => 'wsrep_flow_control_sent', label => 'Pause events sent',
- type => 'DERIVE',
- min => 0,
- negative => 'wsrep_flow_control_recv'},
- ],
- };
-
-
-
-#-------------------------
-
-$graphs{wsrep_flow_paused} = {
- config => {
- global_attrs => {
- title => 'Galera flow control paused ratio',
- },
- data_source_attrs => {
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'wsrep_flow_control_paused', label => 'Ratio flow control was paused',
- type => 'GAUGE',
- min => '0',
- max => '1',
- warning => 0.1,
- critical => 0.9},
- ],
- };
-
-#-------------------------
-
-$graphs{wsrep_flow_paused_ns} = {
- config => {
- global_attrs => {
- title => 'Galera flow control paused time',
- vlabel => 'nanoseconds',
- },
- data_source_attrs => {
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'wsrep_flow_control_paused_ns', label => 'Time flow control was paused (ns)',
- min => '0',
- warning => 20000,
- critical => 1000000},
- ],
- };
-
-#-------------------------
-
-$graphs{wsrep_distance} = {
- config => {
- global_attrs => {
- title => 'Galera distance',
- },
- data_source_attrs => {
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'wsrep_cert_deps_distance', label => 'cert_deps_distance',
- type => 'GAUGE'},
- {name => 'wsrep_cert_index_size', label => 'wsrep_cert_index_size',
- type => 'GAUGE'},
- {name => 'wsrep_slave_threads', label => 'wsrep_slave_threads',
- type => 'GAUGE'},
- {name => 'wsrep_commit_window', label => 'commit_window',
- type => 'GAUGE'},
- ],
-};
-
-#-------------------------
-$graphs{bin_relay_log} = {
- config => {
- global_attrs => {
- title => 'Binary/Relay Logs',
- vlabel => 'Log activity',
- },
- data_source_attrs => {
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'Binlog_cache_disk_use', label => 'Binlog Cache Disk Use'},
- {name => 'Binlog_cache_use', label => 'Binlog Cache Use'},
- {name => 'Binlog_stmt_cache_disk_use', label => 'Binlog Statement Cache Disk Use'},
- {name => 'Binlog_stmt_cache_use', label => 'Binlog Statement Cache Use'},
- {name => 'ma_binlog_size', label => 'Binary Log Space'},
- {name => 'relay_log_space', label => 'Relay Log Space'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{commands} = {
- config => {
- global_attrs => {
- title => 'Command Counters',
- vlabel => 'Commands per ${graph_period}',
- total => 'Questions',
- },
- data_source_attrs => {},
- },
- data_sources => [
- {name => 'Com_delete', label => 'Delete'},
- {name => 'Com_insert', label => 'Insert'},
- {name => 'Com_insert_select', label => 'Insert select'},
- {name => 'Com_load', label => 'Load Data'},
- {name => 'Com_replace', label => 'Replace'},
- {name => 'Com_replace_select', label => 'Replace select'},
- {name => 'Com_select', label => 'Select'},
- {name => 'Com_update', label => 'Update'},
- {name => 'Com_update_multi', label => 'Update multi'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{connections} = {
- config => {
- global_attrs => {
- title => 'Connections',
- vlabel => 'Connections per ${graph_period}',
- },
- data_source_attrs => {
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'max_connections', label => 'Max connections',
- type => 'GAUGE',
- draw => 'AREA',
- colour => 'cdcfc4'},
- {name => 'Max_used_connections', label => 'Max used',
- type => 'GAUGE',
- draw => 'AREA',
- colour => 'ffd660'},
- {name => 'Aborted_clients', label => 'Aborted clients'},
- {name => 'Aborted_connects', label => 'Aborted connects'},
- {name => 'Threads_connected', label => 'Threads connected',
- type => 'GAUGE'},
- {name => 'Threads_running', label => 'Threads running',
- type => 'GAUGE'},
- {name => 'Connections', label => 'New connections'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{files} = {
- config => {
- global_attrs => {
- title => 'Files',
- },
- data_source_attrs => {
- type => 'GAUGE',
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'open_files_limit', label => 'File Limit',
- draw => 'AREA',
- colour => 'cdcfc4'},
- {name => 'Open_files', label => 'Open files',
- type => 'DERIVE',
- min => 0},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{tables} = {
- config => {
- global_attrs => {
- title => 'Tables',
- },
- data_source_attrs => {
- type => 'GAUGE',
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'table_open_cache', label => 'Table cache',
- draw => 'AREA',
- colour => 'cdcfc4'},
- {name => 'innodb_open_files', label => 'Innodb Table Cache Limit',
- draw => 'AREA',
- colour => 'ffd660'},
- {name => 'Open_tables', label => 'Open tables'},
- {name => 'Slave_open_temp_tables', label => 'Open Slave Temp Tables'},
- {name => 'Opened_tables', label => 'Opened tables',
- type => 'DERIVE',
- min => 0},
- {name => 'Opened_views', label => 'Opened Views',
- type => 'DERIVE',
- min => 0},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{table_definitions} = {
- config => {
- global_attrs => {
- title => 'Tables Definitions',
- },
- data_source_attrs => {
- type => 'GAUGE',
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'table_definition_cache', label => 'Cache Limit',
- draw => 'AREA',
- colour => 'cdcfc4'},
- {name => 'Open_table_definitions', label => 'Open'},
- {name => 'Opened_table_definitions', label => 'Opened',
- type => 'DERIVE',
- min => 0},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{innodb_bpool} = {
- config => {
- global_attrs => {
- title => 'InnoDB Buffer Pool',
- vlabel => 'Pages',
- args => '--base 1024',
- },
- data_source_attrs => {
- draw => 'LINE2',
- type => 'GAUGE',
- },
- },
- data_sources => [
- {name => 'ib_bpool_size', label => 'Buffer pool size',
- draw => 'AREA',
- colour => 'ffd660'},
- {name => 'ib_bpool_dbpages', label => 'Database pages',
- draw => 'AREA',
- colour => 'cdcfc4'},
- {name => 'ib_bpool_free', label => 'Free pages'},
- {name => 'ib_bpool_modpages', label => 'Modified pages'},
- {name => 'ib_bpool_oldpages', label => 'Old pages'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{innodb_bpool_act} = {
- config => {
- global_attrs => {
- title => 'InnoDB Buffer Pool Activity',
- vlabel => 'Pages per ${graph_period}',
- total => 'Total',
- },
- data_source_attrs => {
- draw => 'LINE2',
- },
- },
- data_sources => [
- {name => 'ib_bpool_read', label => 'Read'},
- {name => 'ib_bpool_created', label => 'Created'},
- {name => 'ib_bpool_written', label => 'Written'},
- {name => 'ib_bpool_made_young', label => 'Made young'},
- {name => 'ib_bpool_made_not_young', label => 'Made not young'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{innodb_bpool_internal_breakdown} = {
- config => {
- global_attrs => {
- title => 'InnoDB Buffer Pool Internal breakdown',
- args => '--base 1024 --lower-limit 0',
- vlabel => 'bytes',
- },
- data_source_attrs => {
- min => '0',
- draw => 'AREASTACK',
- type => 'GAUGE',
- },
- },
- data_sources => [
- {name => 'ib_bpool_internal_adaptive_hash_size_const', label => 'Adaptive Hash const'},
- {name => 'ib_bpool_internal_adaptive_hash_size_var', label => 'Adaptive Hash var'},
- {name => 'ib_bpool_internal_page_hash_size_total', label => 'Page Hash'},
- {name => 'ib_bpool_internal_dictionary_cache_size_const', label => 'Dictionary const'},
- {name => 'ib_bpool_internal_dictionary_cache_size_var', label => 'Dictionary var'},
- {name => 'ib_bpool_internal_file_system_size_const', label => 'Filesystem const'},
- {name => 'ib_bpool_internal_file_system_size_var', label => 'Filesystem var'},
- {name => 'ib_bpool_internal_lock_system_size_const', label => 'Lock system const'},
- {name => 'ib_bpool_internal_lock_system_size_var', label => 'Lock system var'},
- {name => 'ib_bpool_internal_recovery_system_size_const', label => 'Recovery system const'},
- {name => 'ib_bpool_internal_recovery_system_size_var', label => 'Recovery system var'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{innodb_insert_buf} = {
- config => {
- global_attrs => {
- title => 'InnoDB Insert Buffer',
- vlabel => 'Activity per ${graph_period}',
- },
- data_source_attrs => {
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'ib_ibuf_inserts', label => 'Merge Inserts'},
- {name => 'ib_ibuf_delete', label => 'Merge Deletes'},
- {name => 'ib_ibuf_merged_rec', label => 'Merged Records'},
- {name => 'ib_ibuf_merges', label => 'Merges'},
- {name => 'ib_ibuf_discard_inserts', label => 'Discard Inserts'},
- {name => 'ib_ibuf_discard_delete', label => 'Discard Deletes'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{innodb_adaptive_hash} = {
- config => {
- global_attrs => {
- title => 'InnoDB Adaptive Hash Optimiser',
- },
- data_source_attrs => {
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'Innodb_adaptive_hash_hash_searches', label => 'Hash Searches'},
- {name => 'Innodb_adaptive_hash_non_hash_searches', label => 'Nonhash Searches'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{innodb_io} = {
- config => {
- global_attrs => {
- title => 'InnoDB IO',
- vlabel => 'IO operations per ${graph_period}',
- },
- data_source_attrs => {
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'ib_io_read', label => 'File reads'},
- {name => 'ib_io_write', label => 'File writes'},
- {name => 'ib_io_log', label => 'Log writes'},
- {name => 'ib_io_fsync', label => 'File syncs'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{innodb_io_pend} = {
- config => {
- global_attrs => {
- title => 'InnoDB IO Pending',
- vlabel => 'Pending operations',
- },
- data_source_attrs => {
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'ib_iop_log', label => 'AIO Log'},
- {name => 'ib_iop_sync', label => 'AIO Sync'},
- {name => 'ib_iop_flush_bpool', label => 'Buf Pool Flush'},
- {name => 'ib_iop_flush_log', label => 'Log Flushes'},
- {name => 'ib_iop_ibuf_aio', label => 'Insert Buf AIO Read'},
- {name => 'ib_iop_aioread', label => 'Normal AIO Reads'},
- {name => 'ib_iop_aiowrite', label => 'Normal AIO Writes'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{innodb_log} = {
- config => {
- global_attrs => {
- title => 'InnoDB Log',
- vlabel => 'Log activity per ${graph_period}',
- },
- data_source_attrs => {
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'innodb_log_buffer_size', label => 'Buffer Size',
- type => 'GAUGE',
- draw => 'AREA',
- colour => 'fafd9e'},
- {name => 'ib_log_flush', label => 'KB Flushed'},
- {name => 'ib_log_written', label => 'KB Written'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{innodb_rows} = {
- config => {
- global_attrs => {
- title => 'InnoDB Row Operations',
- vlabel => 'Operations per ${graph_period}',
- total => 'Total',
- },
- data_source_attrs => {},
- },
- data_sources => [
- {name => 'Innodb_rows_deleted', label => 'Deletes'},
- {name => 'Innodb_rows_inserted', label => 'Inserts'},
- {name => 'Innodb_rows_read', label => 'Reads'},
- {name => 'Innodb_rows_updated', label => 'Updates'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{innodb_semaphores} = {
- config => {
- global_attrs => {
- title => 'InnoDB Semaphores',
- vlabel => 'Semaphores per ${graph_period}',
- },
- data_source_attrs => {
- draw => 'AREASTACK',
- },
- },
- data_sources => [
- {name => 'ib_spin_rounds', label => 'Spin Rounds'},
- {name => 'ib_spin_waits', label => 'Spin Waits'},
- {name => 'ib_os_waits', label => 'OS Waits'},
- {name => 'ib_rw_shared_rounds', label => 'RW/S Rounds'},
- {name => 'ib_rw_shared_waits', label => 'RW/S Waits'},
- {name => 'ib_rw_shared_os_waits', label => 'RW/S OS Waits'},
- {name => 'ib_rw_excl_rounds', label => 'RW/X Rounds'},
- {name => 'ib_rw_excl_waits', label => 'RW/X Waits'},
- {name => 'ib_rw_excl_os_waits', label => 'RW/X OS Waits'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{innodb_tnx} = {
- config => {
- global_attrs => {
- title => 'InnoDB Transactions',
- vlabel => 'Transactions per ${graph_period}',
- },
- data_source_attrs => {
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'ib_tnx', label => 'Transactions created'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{innodb_history_list_length} = {
- config => {
- global_attrs => {
- title => 'InnoDB History List Length',
- vlabel => 'Undo log units',
- },
- data_source_attrs => {
- draw => 'LINE1',
- type => 'GAUGE',
- },
- },
- data_sources => [
- {name => 'ib_tnx_hist', label => 'History List Length'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{innodb_srv_master_thread} = {
- config => {
- global_attrs => {
- title => 'InnoDB Master Thread',
- },
- data_source_attrs => {
- type => 'DERIVE',
- draw => 'AREASTACK',
- },
- },
- data_sources => [
- {name => 'ib_srv_main_flush_loops', label => 'Flush Loop'},
- {name => 'ib_srv_main_background_loops', label => 'Background Loop'},
- {name => 'ib_srv_main_flushs_writes', label => 'Flushes/Writes', draw => 'LINE1'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{innodb_queries} = {
- config => {
- global_attrs => {
- title => 'InnoDB Engine Queries and Transactions',
- args => '--lower-limit 0',
- },
- data_source_attrs => {
- type => 'GAUGE',
- },
- },
- data_sources => [
- {name => 'ib_innodb_queries', label => 'Active'},
- {name => 'ib_innodb_transactions_active', label => 'Transactions'},
- {name => 'ib_innodb_query_queue_len', label => 'Queued'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{innodb_read_views} = {
- config => {
- global_attrs => {
- title => 'InnoDB Read Views',
- args => '--lower-limit 0',
- },
- data_source_attrs => {
- type => 'GAUGE',
- },
- },
- data_sources => [
- {name => 'ib_innodb_read_views', label => 'Views'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{innodb_descriptors} = {
- config => {
- global_attrs => {
- title => 'InnoDB Descriptors',
- args => '--lower-limit 0',
- },
- data_source_attrs => {
- type => 'GAUGE',
- },
- },
- data_sources => [
- {name => 'ib_innodb_descriptors', label => 'Descriptors'},
- {name => 'ib_innodb_descriptors_max', label => 'Max', draw => 'AREA', colour => 'ffd660'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{performance} = {
- config => {
- global_attrs => {
- title => 'Performance Schema Losses',
- },
- data_source_attrs => {
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'Performance_schema_cond_classes_lost', label => 'Condition classes'},
- {name => 'Performance_schema_cond_instances_lost', label => 'Condition instances'},
- {name => 'Performance_schema_file_classes_lost', label => 'File classes'},
- {name => 'Performance_schema_file_handles_lost', label => 'File handles'},
- {name => 'Performance_schema_file_instances_lost', label => 'File instances'},
- {name => 'Performance_schema_locker_lost', label => 'Locker'},
- {name => 'Performance_schema_mutex_classes_lost', label => 'Mutex classes'},
- {name => 'Performance_schema_mutex_instances_lost', label => 'Mutex instances'},
- {name => 'Performance_schema_rwlock_classes_lost', label => 'Read/Write lock classes'},
- {name => 'Performance_schema_rwlock_instances_lost', label => 'Read/Write lock instances'},
- {name => 'Performance_schema_table_handles_lost', label => 'Table handles'},
- {name => 'Performance_schema_table_instances_lost', label => 'Table instances'},
- {name => 'Performance_schema_thread_classes_lost', label => 'Thread classes'},
- {name => 'Performance_schema_thread_instances_lost', label => 'Thread instances'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{myisam_indexes} = {
- config => {
- global_attrs => {
- title => 'MyISAM Indexes',
- vlabel => 'Requests per ${graph_period}',
- },
- data_source_attrs => {
- draw => 'LINE2',
- },
- },
- data_sources => [
- {name => 'Key_read_requests', label => 'Key read requests'},
- {name => 'Key_reads', label => 'Key reads'},
- {name => 'Key_write_requests', label => 'Key write requests'},
- {name => 'Key_writes', label => 'Key writes'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{network_traffic} = {
- config => {
- global_attrs => {
- title => 'Network Traffic',
- args => '--base 1024',
- vlabel => 'Bytes received (-) / sent (+) per ${graph_period}',
- },
- data_source_attrs => {
- draw => 'LINE2',
- },
- },
- data_sources => [
- {name => 'Bytes_received', label => 'Bytes transferred',
- graph => 'no'},
- {name => 'Bytes_sent', label => 'Bytes transferred',
- negative => 'Bytes_received'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{qcache} = {
- config => {
- global_attrs => {
- title => 'Query Cache',
- vlabel => 'Commands per ${graph_period}',
- },
- data_source_attrs => {
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'Qcache_queries_in_cache', label => 'Queries in cache', type => 'GAUGE'},
- {name => 'Qcache_hits', label => 'Cache hits'},
- {name => 'Subquery_cache_hit', label => 'Subquery Cache hits'},
- {name => 'Subquery_cache_miss', label => 'Subquery Cache misses'},
- {name => 'Qcache_inserts', label => 'Inserts'},
- {name => 'Qcache_not_cached', label => 'Not cached'},
- {name => 'Qcache_lowmem_prunes', label => 'Low-memory prunes'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{qcache_mem} = {
- config => {
- global_attrs => {
- title => 'Query Cache Memory',
- vlabel => 'Bytes',
- args => '--base 1024 --lower-limit 0',
- },
- data_source_attrs => {
- draw => 'AREA',
- type => 'GAUGE',
- },
- },
- data_sources => [
- {name => 'query_cache_size', label => 'Cache size'},
- {name => 'Qcache_free_memory', label => 'Free mem'},
- ],
-};
-
-
-#---------------------------------------------------------------------
-
-$graphs{max_mem} = {
- config => {
- global_attrs => {
- title => 'Maximum memory that Mysql could use',
- vlabel => 'Bytes',
- args => '--base 1024 --lower-limit 0',
- },
- data_source_attrs => {
- draw => 'AREASTACK',
- type => 'GAUGE',
- },
- },
- data_sources => [
- {name => 'mysql_connection_memory', label => 'Connection Memory'},
- {name => 'mysql_base_memory', label => 'Base MYSQL Memory'},
- ],
-};
-
-
-#---------------------------------------------------------------------
-
-$graphs{replication} = {
- config => {
- global_attrs => {
- title => 'Replication',
- vlabel => 'Activity',
- },
- data_source_attrs => {
- draw => 'LINE1',
- },
- },
- data_sources => [
- {name => 'slave_io_running', label => 'Slave IO Running',
- type => 'GAUGE',
- draw => 'AREA'},
- {name => 'slave_sql_running', label => 'Slave SQL Running',
- type => 'GAUGE',
- draw => 'AREA'},
- {name => 'Slave_retried_transactions', label => 'Retried Transactions'},
- {name => 'Slave_open_temp_tables', label => 'Open Temp Tables'},
- {name => 'seconds_behind_master', label => 'Secs Behind Master',
- type => 'GAUGE'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{select_types} = {
- config => {
- global_attrs => {
- title => 'Select types',
- vlabel => 'Commands per ${graph_period}',
- total => 'Total',
- },
- data_source_attrs => {},
- },
- data_sources => [
- {name => 'Select_full_join', label => 'Full join'},
- {name => 'Select_full_range_join', label => 'Full range'},
- {name => 'Select_range', label => 'Range'},
- {name => 'Select_range_check', label => 'Range check'},
- {name => 'Select_scan', label => 'Scan'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{slow} = {
- config => {
- global_attrs => {
- title => 'Slow Queries',
- vlabel => 'Slow queries per ${graph_period}',
- },
- data_source_attrs => {
- draw => 'LINE2',
- },
- },
- data_sources => [
- {name => 'Slow_queries', label => 'Slow queries'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{sorts} = {
- config => {
- global_attrs => {
- title => 'Sorts',
- vlabel => 'Sorts / ${graph_period}',
- },
- data_source_attrs => {
- draw => 'LINE2',
- },
- },
- data_sources => [
- {name => 'Sort_rows', label => 'Rows sorted'},
- {name => 'Sort_range', label => 'Range'},
- {name => 'Sort_merge_passes', label => 'Merge passes'},
- {name => 'Sort_scan', label => 'Scan'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{table_locks} = {
- config => {
- global_attrs => {
- title => 'Table locks',
- vlabel => 'locks per ${graph_period}',
- },
- data_source_attrs => {
- draw => 'LINE2',
- },
- },
- data_sources => [
- {name => 'Table_locks_immediate', label => 'Table locks immed'},
- {name => 'Table_locks_waited', label => 'Table locks waited'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{tmp_tables} = {
- config => {
- global_attrs => {
- title => 'Temporary objects',
- vlabel => 'Objects per ${graph_period}',
- },
- data_source_attrs => {
- draw => 'LINE2',
- },
- },
- data_sources => [
- {name => 'Created_tmp_disk_tables', label => 'Temp disk tables'},
- {name => 'Created_tmp_tables', label => 'Temp tables'},
- {name => 'Created_tmp_files', label => 'Temp files'},
- ],
-};
-
-
-#---------------------------------------------------------------------
-
-$graphs{rows} = {
- config => {
- global_attrs => {
- title => 'Rows',
- },
- data_source_attrs => {
- draw => 'LINE2',
- type => 'DERIVE',
- },
- },
- data_sources => [
- {name => 'Rows_read', label => 'Read'},
- {name => 'Rows_sent', label => 'Sent'},
- {name => 'Rows_tmp_read', label => 'Temp Read'},
- ],
- };
-
-#---------------------------------------------------------------------
-
-$graphs{handler_read} = {
- config => {
- global_attrs => {
- title => 'Read Handler',
- },
- data_source_attrs => {
- draw => 'AREASTACK',
- type => 'DERIVE',
- },
- },
- data_sources => [
- {name => 'Handler_read_first', label => 'Key First'},
- {name => 'Handler_read_key', label => 'Key Read'},
- {name => 'Handler_read_last', label => 'Key Last'},
- {name => 'Handler_read_prev', label => 'Key Prev'},
- {name => 'Handler_read_rnd', label => 'Row position'},
- {name => 'Handler_read_rnd_deleted', label => 'Row position delete'},
- {name => 'Handler_read_rnd_next', label => 'Row position next'},
- ],
- };
-
-#---------------------------------------------------------------------
-
-$graphs{handler_transaction} = {
- config => {
- global_attrs => {
- title => 'Transactions Handler',
- },
- data_source_attrs => {
- draw => 'AREASTACK',
- type => 'DERIVE',
- },
- },
- data_sources => [
- {name => 'Handler_commit', label => 'Commit'},
- {name => 'Handler_rollback', label => 'Rollback'},
- {name => 'Handler_savepoint', label => 'Savepoint'},
- {name => 'Handler_savepoint_rollback', label => 'Savepoint Rollback'},
- ],
- };
-
-#---------------------------------------------------------------------
-
-$graphs{handler_write} = {
- config => {
- global_attrs => {
- title => 'Write/Update Handler',
- },
- data_source_attrs => {
- draw => 'LINE2',
- type => 'DERIVE',
- },
- },
- data_sources => [
- {name => 'Handler_write', label => 'Writes'},
- {name => 'Handler_update', label => 'Updates'},
- ],
- };
-
-#---------------------------------------------------------------------
-
-$graphs{handler_tmp} = {
- config => {
- global_attrs => {
- title => 'Temporary Write/Update Handler',
- },
- data_source_attrs => {
- draw => 'LINE2',
- type => 'DERIVE',
- },
- },
- data_sources => [
- {name => 'Handler_tmp_write', label => 'Writes'},
- {name => 'Handler_tmp_update', label => 'Updates'},
- ],
- };
-
-#---------------------------------------------------------------------
-
-$graphs{execution} = {
- config => {
- global_attrs => {
- title => 'Execution Events',
- },
- data_source_attrs => {
- draw => 'LINE2',
- type => 'DERIVE',
- },
- },
- data_sources => [
- {name => 'Executed_events', label => 'Events'},
- {name => 'Executed_triggers', label => 'Triggers'},
- ],
- };
-
-#---------------------------------------------------------------------
-
-$graphs{icp} = {
- config => {
- global_attrs => {
- title => 'Index Condition Pushdown',
- },
- data_source_attrs => {
- draw => 'LINE2',
- type => 'DERIVE',
- },
- },
- data_sources => [
- {name => 'Handler_icp_attempts', label => 'Attempts'},
- {name => 'Handler_icp_match', label => 'Matches'},
- ],
-};
-
-#---------------------------------------------------------------------
-
-$graphs{mrr} = {
- config => {
- global_attrs => {
- title => 'Multi Range Read optimizations',
- },
- data_source_attrs => {
- draw => 'LINE2',
- type => 'DERIVE',
- },
- },
- data_sources => [
- {name => 'Handler_mrr_init', label => 'Uses'},
- {name => 'Handler_mrr_key_refills', label => 'Key refills'},
- {name => 'Handler_mrr_rowid_refills', label => 'Row refills'},
- ],
-};
-
-#---------------------------------------------------------------------
-# Plugin Graphs
-# These are mysql plugins of type INFORMATION SCHEMA
-#
-# These will be added to $graphs if available
-#---------------------------------------------------------------------
-
-my %graph_plugins = ();
-
-$graph_plugins{query_response_time} = {
- count => {
- config => {
- global_attrs => {
- title => 'Query Response Time Count',
- vlabel => 'queries per ${graph_period}',
- },
- data_source_attrs => {
- draw => 'LINE2',
- type => 'DERIVE',
- },
- },
- # data_sources are populated by sub plugin_query_response_time
- data_sources => [
- ],
- },
- total => {
- config => {
- global_attrs => {
- title => 'Query Response Time Total',
- vlabel => 'query time (microseconds) per ${graph_period}',
- },
- data_source_attrs => {
- draw => 'LINE2',
- type => 'DERIVE',
- },
- },
- # data_sources are populated by sub plugin_query_response_time
- data_sources => [
- ],
- }
-};
-
-$graph_plugins{user_statistics} = {
- connections => {
- config => {
- global_attrs => {
- title => 'User Connections',
- vlabel => 'connections per ${graph_period}',
- },
- data_source_attrs => {
- draw => 'LINE2',
- type => 'DERIVE',
- },
- },
- cols => { 'total_connections' => {}, 'concurrent_connections' => {}, 'denied_connections' => {}, 'lost_connections' => {}},
- data_sources => [
- ],
- },
- usertime => {
- config => {
- global_attrs => {
- title => 'User Time',
- vlabel => 'seconds',
- },
- data_source_attrs => {
- draw => 'LINE2',
- type => 'DERIVE',
- },
- },
- cols => { 'connected_time' => {}, 'busy_time' => {}, 'cpu_time' => {} },
- data_sources => [
- ],
- },
- bytes => {
- config => {
- global_attrs => {
- title => 'User Bytes',
- vlabel => 'bytes',
- },
- data_source_attrs => {
- draw => 'LINE2',
- type => 'DERIVE',
- },
- },
- cols => { 'bytes_received' => {}, 'bytes_sent' => {}, 'binlog_bytes_written' => {} },
- data_sources => [
- ],
- },
- rows => {
- config => {
- global_attrs => {
- title => 'User Rows',
- vlabel => 'rows',
- },
- data_source_attrs => {
- draw => 'LINE2',
- type => 'DERIVE',
- },
- },
- cols => { 'rows_read' => {}, 'rows_sent' => {}, 'rows_deleted' => {}, 'rows_inserted' => {}, 'rows_updated' => {} },
- data_sources => [
- ],
- },
- commands => {
- config => {
- global_attrs => {
- title => 'Command breakdown by user',
- vlabel => 'commands',
- },
- data_source_attrs => {
- draw => 'LINE2',
- type => 'DERIVE',
- },
- },
- cols => { 'select_commands' => {}, 'update_commands' => {}, 'other_commands' => {}, 'commit_transactions' => {}, 'rollback_transactions' => {} },
- data_sources => [
- ],
- }
-
-};
-#---------------------------------------------------------------------
-# M A I N
-#---------------------------------------------------------------------
-
-
-#
-# Global hash holding the data collected from mysql.
-#
-our $data; # Was 'my'. Changed to 'our' to facilitate testing.
-
-
-sub main {
- my $graph = basename($0);
- $graph =~ s/^mysql[0-9]*_//g; # allow multiple instances
- my $command = $ARGV[0] || 'show';
-
- my %command_map = (
- 'autoconf' => \&autoconf,
- 'config' => \&config,
- 'show' => \&show,
- 'suggest' => \&suggest,
- );
-
- die "Unknown command: $command"
- unless exists $command_map{$command};
-
- die "Missing dependency Cache::Cache"
- unless $has_cache || $command eq 'autoconf';
-
- return $command_map{$command}->($graph);
-}
-
-
-#---------------------------------------------------------------------
-# C O M M A N D H A N D L E R S
-#---------------------------------------------------------------------
-
-# Each command handler should return an appropriate exit code
-
-
-# http://munin-monitoring.org/wiki/ConcisePlugins#autoconf
-sub autoconf {
- unless ($has_cache) {
- print "no (Missing dependency Cache::Cache)\n";
- return 0;
- }
-
- eval {
- db_connect();
- };
- if ($@) {
- my $err = $@;
- $err =~ s{\s at \s \S+ \s line .*}{}xms;
- print "no ($err)\n";
- return 0;
- }
- print "yes\n";
- return 0;
-}
-
-
-# http://munin-monitoring.org/wiki/ConcisePlugins#suggest
-sub suggest {
-
- # What is the best way to decide which graphs is applicable to a
- # given system?
- # Answer:
- # Use lack of variables to indicate that the capability doesn't exist
- # Use variable values to indicate some graph isn't currently used.
- # update_data() now does this.
-
- update_data();
-
-
- foreach my $graph (sort keys(%graphs)) {
- next if $graph =~ /innodb_/ && $data->{_innodb_disabled};
- next if $graph =~ /wsrep_/ && $data->{_galera_disabled};
- print "$graph\n";
- }
-
- return 0;
-}
-
-
-sub config {
- my $graph_name = shift;
-
- # In MySQL 5.1 (and probably erlier versions as well) status
- # variables are unique when looking at the last 19 characters.
- #
- # SELECT RIGHT(variable_name, 19), COUNT(*)
- # FROM information_schema.global_status
- # GROUP BY RIGHT(variable_name, 19)
- # HAVING COUNT(*) > 1;
- #
- # Empty set (0.06 sec)
- #
- # There is one duplicate when looking at server variables
- #
- # SELECT RIGHT(variable_name, 19), COUNT(*)
- # FROM information_schema.global_variables
- # GROUP BY RIGHT(variable_name, 19)
- # HAVING COUNT(*) > 1;
- #
- # +--------------------------+----------+
- # | RIGHT(variable_name, 19) | COUNT(*) |
- # +--------------------------+----------+
- # | OW_PRIORITY_UPDATES | 2 |
- # +--------------------------+----------+
- # 1 row in set (0.05 sec)
- #
- # show global variables like '%OW_PRIORITY_UPDATES';
- #
- # +--------------------------+-------+
- # | Variable_name | Value |
- # +--------------------------+-------+
- # | low_priority_updates | OFF |
- # | sql_low_priority_updates | OFF |
- # +--------------------------+-------+
- # 2 rows in set (0.00 sec)
- #
- # Not a problem since we don't graph these
-
- update_data();
-
- die 'Unknown graph ' . ($graph_name ? $graph_name : '')
- unless $graphs{$graph_name};
-
- my $graph = $graphs{$graph_name};
-
- my %conf = (%{$defaults{global_attrs}}, %{$graph->{config}{global_attrs}});
- while (my ($k, $v) = each %conf) {
- print "graph_$k $v\n";
- }
- if ($graph_name =~ /wsrep_/) {
- print "graph_category galera\n";
- } else {
- print "graph_category mysql\n";
- }
-
- my $i = 0;
- for my $ds (@{$graph->{data_sources}}) {
- my %ds_spec = (
- %{$defaults{data_source_attrs}},
- %{$graph->{config}{data_source_attrs}},
- %$ds,
- );
- while (my ($k, $v) = each %ds_spec) {
- # 'name' is only used internally in this script, not
- # understood by munin.
- next if ($k eq 'name');
-
- # AREASTACK is part of munin as of version 1.3.3 (not
- # released yet). Until then ...
- if ($k eq 'draw' && $v eq 'AREASTACK') {
- printf("%s.%s %s\n",
- clean_fieldname($ds->{name}), $k, ($i ? 'STACK' : 'AREA'));
- }
- else {
- printf("%s.%s %s\n", clean_fieldname($ds->{name}), $k, $v);
- }
- $i++;
- }
- print_thresholds(clean_fieldname($ds->{name}));
- }
-
- return 0;
-}
-
-sub show {
- my $graph_name = shift;
-
- update_data();
-
- die 'Unknown graph ' . ($graph_name ? $graph_name : '')
- unless $graphs{$graph_name};
-
- my $graph = $graphs{$graph_name};
-
- die "Can't show data for '$graph_name' because InnoDB is disabled."
- if $graph_name =~ /innodb_/ && $data->{_innodb_disabled};
-
- die "Can't show data for '$graph_name' because not a Galera mysql version."
- if $graph_name =~ /wsrep_/ && $data->{_galera_disabled};
-
- for my $ds (@{$graph->{data_sources}}) {
- printf "%s.value %s\n",
- clean_fieldname($ds->{name}),
- defined $data->{$ds->{name}} ? $data->{$ds->{name}} : 'U';
- }
-
- return 0;
-}
-
-
-
-#---------------------------------------------------------------------
-# U T I L I T Y S U B S
-#---------------------------------------------------------------------
-
-
-sub db_connect {
- my $dsn = "$config{dsn};mysql_connect_timeout=5";
-
- return DBI->connect($dsn, $config{user}, $config{password}, {
- RaiseError => 1,
- PrintError => 0,
- FetchHashKeyName => 'NAME_lc',
- });
-}
-
-
-sub update_data {
- $data = $shared_memory_cache->get('data');
- my $graphs_stored = $shared_memory_cache->get('graphs');
- %graphs = %{thaw($graphs_stored)} if $graphs_stored;
- return if $data;
-
- $data = {};
-
- my $dbh = db_connect();
-
- update_variables($dbh);
- update_plugins($dbh);
- update_innodb($dbh);
- update_master($dbh);
- delete $graphs{replication} if update_slave($dbh)==1;
-
- delete $graphs{bin_relay_log} if not defined $data->{relay_log_space}
- && not defined $data->{ma_binlog_size};
-
- delete $graphs{execution} if not defined $data->{Executed_events}
- && not defined $data->{Executed_triggers};
-
- delete $graphs{icp} if not defined $data->{Handler_icp_attempts}
- && not defined $data->{Handler_icp_matches};
-
- delete $graphs{innodb_adaptive_hash}
- if not defined $data->{Innodb_adaptive_hash_hash_searches}
- && not defined $data->{Innodb_adaptive_hash_non_hash_searches};
-
- delete $graphs{innodb_bpool_internal_breakdown}
- if not defined $data->{ib_bpool_internal_adaptive_hash_size_const};
-
- delete $graphs{innodb_descriptors}
- if not defined $data->{ib_innodb_descriptors};
-
- delete $graphs{mrr} if not defined $data->{Handler_mrr_init};
-
- delete $graphs{rows} if not defined $data->{Rows_sent};
-
- delete $graphs{handler_temp} if not defined $data->{Handler_tmp_write};
-
- $shared_memory_cache->set('data', $data);
- $shared_memory_cache->set('graphs', nfreeze(\%graphs));
-}
-
-
-sub update_plugins {
- my ($dbh) = @_;
-
- my %plugin_map = (
- 'query_response_time' => \&plugin_query_response_time,
- );
-
- sub add_graphs {
- my ($f, $sec, $dbh, %g) = @_;
- if ($f->($dbh) == 0) {
- while (my ($k, $v) = each %g) {
- $graphs{$sec . '_' . $k} = $v;
- }
- }
- }
-
- my $sth = $dbh->prepare("SHOW PLUGINS");
- $sth->execute();
- while (my $row = $sth->fetchrow_hashref()) {
- next if $row->{'type'} ne 'INFORMATION SCHEMA';
- my $sec = lc $row->{'name'};
- next if not exists $plugin_map{$sec};
- add_graphs($plugin_map{$sec}, $sec, $dbh, %{$graph_plugins{$sec}});
- }
- $sth->finish();
-
- my %is_map = (
- 'user_statistics' => \&is_user_statistics,
- );
-
- $sth = $dbh->prepare("SHOW TABLES IN INFORMATION_SCHEMA");
- $sth->execute();
- while (my $row = $sth->fetchrow_hashref()) {
- my $sec = lc $row->{'tables_in_information_schema'};
- next if not exists $is_map{$sec};
- add_graphs($is_map{$sec}, $sec, $dbh, %{$graph_plugins{$sec}});
- }
- $sth->finish();
-}
-
-sub update_variables {
- my ($dbh) = @_;
- my @queries = (
- 'SHOW GLOBAL STATUS',
- 'SHOW GLOBAL VARIABLES',
- );
-
- my %variable_name_map = (
- table_cache => 'table_open_cache', # table_open_cache was
- # previously known as
- # table_cache in MySQL
- # 5.1.2 and earlier.
- );
- my %wsrep_cluster_status_map = (
- 'Primary' => 0,
- 'non-Primary' => 1,
- );
-
- for my $query (@queries) {
- $data->{$query} = {};
-
- my $sth = $dbh->prepare($query);
- $sth->execute();
- while (my $row = $sth->fetch) {
- my $var = $variable_name_map{$row->[0]} || $row->[0];
- $data->{$var} = $row->[1];
- }
- $sth->finish();
- }
-
- $data->{'mysql_base_memory'} = $data->{'key_buffer_size'}
- + $data->{'query_cache_size'}
- + $data->{'innodb_buffer_pool_size'}
- + ( $data->{'innodb_additional_mem_pool_size'} || 0 )
- + $data->{'innodb_log_buffer_size'}
- + ( $data->{'tokudb_cache_size'} || 0 );
-
- my $tmp_table_size = $data->{'tmp_table_size'};
- my $max_heap_table_size = $data->{'max_heap_table_size'};
- $data->{'mysql_connection_memory'} = $data->{'read_buffer_size'}
- + $data->{'read_rnd_buffer_size'}
- + $data->{'sort_buffer_size'}
- + $data->{'join_buffer_size'}
- + $data->{'binlog_cache_size'}
- + $data->{'thread_stack'}
- + ( $tmp_table_size >= $max_heap_table_size ? $tmp_table_size : $max_heap_table_size )
- + ( $data->{'tokudb_read_buf_size'} || 0 );
-
- # wsrep_thread_count was separated from max_connections for mariadb-5.5.38 https://mariadb.atlassian.net/browse/MDEV-6206
- $data->{'mysql_connection_memory'} *= $data->{'max_connections'} + ( $data->{'wsrep_thread_count'} || 0 );
-
- if ($data->{wsrep_cluster_status}) {
- my $var = $wsrep_cluster_status_map{$data->{wsrep_cluster_status}};
- $data->{wsrep_cluster_status} = $var;
- }
- $data->{_galera_disabled} = 1 unless ($data->{wsrep_provider_name});
-}
-
-
-sub update_innodb {
- my ($dbh) = @_;
-
- my $sth = $dbh->prepare('SHOW /*!50000 ENGINE*/ INNODB STATUS');
- eval {
- $sth->execute();
- };
- if ($@) {
- if ($@ =~ /Unknown (storage|table) engine 'INNODB'|Cannot call SHOW INNODB STATUS because skip-innodb is defined/i) {
- $data->{_innodb_disabled} = 1;
- return;
- }
- die $@;
- }
- my $row = $sth->fetchrow_hashref();
- my $status = $row->{'status'};
- $sth->finish();
-
- parse_innodb_status($status);
-}
-
-
-sub update_master {
- my ($dbh) = @_;
-
- my $sth = $dbh->prepare('SHOW MASTER LOGS');
- eval {
- $sth->execute();
- };
- if ($@) {
- # SHOW MASTER LOGS failed because binlog is not enabled
- return if $@ =~ /You are not using binary logging/;
- die $@;
- }
-
- while (my $row = $sth->fetch) {
- $data->{ma_binlog_size} += $row->[1];
- }
-
- $sth->finish();
-}
-
-
-sub update_slave {
- my ($dbh) = @_;
-
- my $sth = $dbh->prepare('SHOW SLAVE STATUS');
- $sth->execute();
- my $row = $sth->fetchrow_hashref();
- return 1 unless $row;
- while (my ($k, $v) = each %$row) {
- $data->{$k} = $v;
- }
- $sth->finish();
-
- # We choose master_host here as a stopped slave
- # may not indicate that we have reset all slave capability
- # however the minimium requirement is a master_host
- return 1 if not defined $data->{master_host};
-
- # undef when slave is stopped, or when MySQL fails to calculate
- # the lag (which happens depresingly often). (mk-heartbeat fixes
- # this problem.)
- $data->{seconds_behind_master} ||= 0;
-
- # Track these two fields so we can trigger warnings if the slave stops
- # running
- $data->{slave_sql_running} = ($data->{slave_sql_running} eq 'Yes')
- ? 0 : 1;
- $data->{slave_io_running} = ($data->{slave_io_running} eq 'Yes')
- ? 0 : 1;
- return 0;
-}
-
-
-#---------------------------------------------------------------------
-# Information SCHEMA tables represent data to be processed
-#---------------------------------------------------------------------
-
-
-sub plugin_query_response_time {
- my ($dbh) = @_;
-
- return 1 if not defined $data->{query_response_time_stats};
- return 1 if $data->{query_response_time_stats} eq 'OFF';
-
- my $sth = $dbh->prepare("SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME");
- $sth->execute();
- while (my $row = $sth->fetchrow_hashref()) {
- my $time = $row->{'time'};
- $data->{'query_response_time_count_' . $time} = $row->{'count'};
- push @{$graph_plugins{query_response_time}->{count}->{data_sources}}, {name => 'query_response_time_count_' . $time, label => $time };
- next if $row->{'total'} eq 'TOO LONG';
- $data->{'query_response_time_total_' . $time} = $row->{'total'} * 1e6;
- push @{$graph_plugins{query_response_time}->{total}->{data_sources}}, {name => 'query_response_time_total_' . $time, label => $time };
- }
- $sth->finish();
-
- return 0;
-}
-
-sub is_user_statistics {
- my ($dbh) = @_;
-
- return 1 if not defined $data->{userstat};
- return 1 if $data->{userstat} eq 'OFF';
-
- my $sth = $dbh->prepare("SELECT * FROM INFORMATION_SCHEMA.USER_STATISTICS");
- $sth->execute();
- while (my $row = $sth->fetchrow_hashref()) {
- my $user = $row->{'user'};
- my $var;
- while (my ($g, $v) = each %{$graph_plugins{user_statistics}}) {
- while (my ($userstat,$conf) = each %{$v->{cols}}) {
- $var = 'user_stats_' . $user . '_' . $userstat;
- $data->{$var} = int $row->{$userstat};
- my $ds = { %$conf };
- $ds->{name} = $var;
- $ds->{label} = $user . ' ' . $userstat;
- push @{$graph_plugins{user_statistics}->{$g}->{data_sources}}, $ds;
- }
- }
- }
- $sth->finish();
- return 0;
-}
-
-#
-# In 'SHOW ENGINE INNODB STATUS' 64 bit integers are not formated as
-# plain integers. They are either:
-#
-# - split in two and needs to be shifted together,
-# - or hexadecimal
-#
-sub innodb_bigint {
- my ($x, $y) = @_;
-
- return defined $y
- ? Math::BigInt->new($x)->blsft(32) + $y
- : Math::BigInt->new("0x$x");
-}
-
-#---------------------------------------------------------------------
-# P A R S E 'SHOW ENGINE INNODB STATUS' O U T P U T
-#---------------------------------------------------------------------
-
-
-# A nice walk through
-# http://www.mysqlperformanceblog.com/2006/07/17/show-innodb-status-walk-through/
-
-# The parsing is split in one subrutine per section. Each subroutine
-# should parse a block with the following structure
-#
-# block body ...
-# more lines ....
-# ----------
-
-sub parse_innodb_status {
- local $_ = shift;
-
- # Add a dummy section to the end in case the innodb status output
- # has been truncated (Happens for status > 64K characters)
- $_ .= "\n----------\nDUMMY\n----------\n";
-
- my %section_map = (
-
- 'BUFFER POOL AND MEMORY' => \&parse_buffer_pool_and_memory,
- 'INDIVIDUAL BUFFER POOL INFO' => \&parse_individual_buffer_pool,
- 'FILE I/O' => \&parse_file_io,
- 'INSERT BUFFER AND ADAPTIVE HASH INDEX'
- => \&parse_insert_buffer_and_adaptive_hash_index,
- 'LATEST DETECTED DEADLOCK' => \&skip,
- 'LATEST FOREIGN KEY ERROR' => \&skip,
- 'LOG' => \&parse_log,
- 'ROW OPERATIONS' => \&parse_row_operations,
- 'SEMAPHORES' => \&parse_semaphores,
- 'TRANSACTIONS' => \&parse_transactions,
- 'BACKGROUND THREAD' => \&parse_background_thread,
- );
-
- skip_heading();
- parse_header_seconds();
- for (;;) {
- m/\G(.*)\n/gc;
- my $sec = $1;
-
- last if $sec eq 'END OF INNODB MONITOR OUTPUT';
- if ($sec eq 'DUMMY') {
- handle_incomplete_innodb_status();
- last;
- }
-
- if (exists $section_map{$sec}) {
- $section_map{$sec}->();
- } else {
- #warn "Unknown section: $1";
- skip();
- }
- }
-}
-
-
-# This regular expression handles the different formating of 64-bit
-# integers in different versions of the innodb engine. Either two
-# decimal 32-bit integers separated by a space, or a single
-# hexadecimal 64-bit integer.
-my $innodb_bigint_rx = qr{([[a-fA-F\d]+)(?: (\d+))?};
-
-
-sub match_new_section {
- return m/\G
- -+\n # ---------------------------
- (?= [A-Z\/ ]+\n # SECTION NAME
- [=-]+\n)/gcx; # --------------------------- ('=' on end of output)
-}
-
-
-sub skip_line { return m/\G.*\n/gc; }
-
-
-sub skip_heading {
- # Heading is 3 lines
- for my $foo (1...3) {
- skip_line or die('Parse error');
- }
-}
-
-
-sub parse_section {
- my ($parser) = @_;
-
- #warn substr($_, pos(), 10);
- for (;;) {
- return if match_new_section;
- next if $parser->();
- skip_line();
- }
-}
-
-
-sub skip { parse_section(sub {}); }
-
-
-sub parse_header_seconds {
- parse_section(
- sub {
- m/\GPer second averages calculated from the last (\d+) seconds\n/gc && do {
- $data->{innodb_engine_status_seconds} = $1;
- return 1;
- };
- }
- );
-}
-
-
-sub parse_background_thread {
- parse_section(
- sub {
- m/\Gsrv_master_thread loops: \d+ 1_second, \d+ sleeps, \d+ 10_second, (\d+) background, (\d+) flush\n/gc && do {
- $data->{ib_srv_main_flush_loops} = $1;
- $data->{ib_srv_main_background_loops} = $2;
- return 1;
- };
- m/\Gsrv_master_thread log flush and writes: (\d+)\n/gc && do {
- $data->{ib_srv_main_flushs_writes} = $1;
- return 1;
- };
- }
- );
-}
-
-sub parse_row_operations {
- parse_section(
- sub {
- m/\G(\d+) queries inside InnoDB, (\d+) queries in queue\n/gc && do {
- $data->{ib_innodb_queries} = $1;
- $data->{ib_innodb_query_queue_len} = $2;
- return 1;
- };
- m/\G(\d+) read views open inside InnoDB\n/gc && do {
- $data->{ib_innodb_read_views} = $1;
- return 1;
- };
- m/\G(\d+) transactions active inside InnoDB\n/gc && do {
- $data->{ib_innodb_transactions_active} = $1;
- return 1;
- };
- m/\G(\d+) out of (\d+) descriptors used\n/gc && do {
- $data->{ib_innodb_descriptors} = $1;
- $data->{ib_innodb_descriptors_max} = $2;
- return 1;
- };
- # no need for this - its exposed as status variables
- # m/\GNumber of rows inserted (\d+), updated (\d+), deleted (\d+), read (\d+)\n/gc && do {
- # $data->{ib_innodb_rows_inserted} = $1;
- # $data->{ib_innodb_rows_updated} = $2;
- # $data->{ib_innodb_rows_deleted} = $3;
- # $data->{ib_innodb_rows_read} = $4;
- # return 1;
- # };
- }
- );
-}
-
-sub parse_semaphores {
- parse_section(
- sub {
- m/\GMutex spin waits (\d+), rounds (\d+), OS waits (\d+)\n/gc && do {
- $data->{ib_spin_waits} = $1;
- $data->{ib_spin_rounds} = $2;
- $data->{ib_os_waits} = $3;
- return 1;
- };
- m/\GRW-shared spins (\d+), rounds (\d+), OS waits (\d+)\n/gc && do {
- $data->{ib_rw_shared_waits} = $1;
- $data->{ib_rw_shared_rounds} = $2;
- $data->{ib_rw_shared_os_waits} = $3;
- return 1;
- };
- m/\GRW-excl spins (\d+), rounds (\d+), OS waits (\d+)\n/gc && do {
- $data->{ib_rw_excl_waits} = $1;
- $data->{ib_rw_excl_rounds} = $2;
- $data->{ib_rw_excl_os_waits} = $3;
- return 1;
- };
- }
- );
-}
-
-
-sub parse_transactions {
- parse_section(
- sub {
- m/\GTrx id counter $innodb_bigint_rx\n/gc && do {
- $data->{ib_tnx} = innodb_bigint($1, $2);
- return 1;
- };
- m/\GPurge done for trx's n:o < $innodb_bigint_rx undo n:o < $innodb_bigint_rx\n/gc && do {
- if (defined $3) {
- # old format
- $data->{ib_tnx_prg} = innodb_bigint($1, $2);
- # FIX add to data? innodb_bigint($3, $4);
- }
- else {
- # new format
- $data->{ib_tnx_prg} = innodb_bigint($1);
- # FIX add to data? innodb_bigint($2);
- }
- return 1;
- };
- m/\GHistory list length (\d+)\n/gc && do {
- $data->{ib_tnx_hist} = $1;
- return 1;
- };
- }
- );
-
-}
-
-
-sub parse_file_io {
- parse_section(
- sub {
- m/\GPending normal aio reads: (\d+)(?: \[(?:\d+, )*\d+\] )?, aio writes: (\d+)(?: \[(?:\d+, )*\d+\] )?,\n\s*ibuf aio reads: (\d+), log i\/o's: (\d+), sync i\/o's: (\d+)\n/gc && do {
- $data->{ib_iop_aioread} = $1;
- $data->{ib_iop_aiowrite} = $2;
- $data->{ib_iop_ibuf_aio} = $3;
- $data->{ib_iop_log} = $4;
- $data->{ib_iop_sync} = $5;
- return 1;
- };
- m/\GPending flushes \(fsync\) log: (\d+); buffer pool: (\d+)\n/gc && do {
- $data->{ib_iop_flush_log} = $1;
- $data->{ib_iop_flush_bpool} = $2;
- return 1;
- };
- m/\G(\d+) OS file reads, (\d+) OS file writes, (\d+) OS fsyncs\n/gc && do {
- $data->{ib_io_read} = $1;
- $data->{ib_io_write} = $2;
- $data->{ib_io_fsync} = $3;
- return 1;
- };
- }
- );
-}
-
-
-sub parse_insert_buffer_and_adaptive_hash_index {
- parse_section(
- sub {
- # MySQL < 5.5
- m/\G(\d+) inserts, (\d+) merged recs, (\d+) merges\n/gc && do {
- $data->{ib_ibuf_inserts} = $1;
- $data->{ib_ibuf_merged_rec} = $2;
- $data->{ib_ibuf_merges} = $3;
- return 1;
- };
- # MySQL >= 5.5
- m/\Gmerged operations:\n insert (\d+), delete mark (\d+), delete (\d+)\ndiscarded operations:\n insert (\d+), delete mark (\d+), delete (\d+)\n/gc && do {
- $data->{ib_ibuf_inserts} = $1;
- $data->{ib_ibuf_delete_mark} = $2;
- $data->{ib_ibuf_delete} = $3;
- $data->{ib_ibuf_discard_inserts} = $4;
- $data->{ib_ibuf_discard_delete_mark} = $5;
- $data->{ib_ibuf_discard_delete} = $6;
- $data->{ib_ibuf_merged_rec} = $data->{ib_ibuf_inserts} + $data->{ib_ibuf_discard_inserts};
- return 1;
- };
-
- m/\GIbuf: size (\d+), free list len (\d+), seg size (\d+),(?: (\d+) merges)?\n/gc && do {
- $data->{ib_ibuf_size} = $1;
- $data->{ib_ibuf_free_len} = $2;
- $data->{ib_ibuf_seg_size} = $3;
- $data->{ib_ibuf_merges} = $4 if defined $4; # MySQL >= 5.5
- return 1;
- };
- }
- );
-}
-
-
-sub parse_log {
- parse_section(
- sub {
- m/\GLog sequence number $innodb_bigint_rx\n/gc && do {
- $data->{ib_log_written} = innodb_bigint($1, $2);
- return 1;
- };
- m/\GLog flushed up to\s+$innodb_bigint_rx\n/gc && do {
- $data->{ib_log_flush} = innodb_bigint($1, $2);
- return 1;
- };
- m/\G(\d+) log i\/o's done.*\n/gc && do {
- $data->{ib_io_log} = $1;
- return 1;
- };
- }
- );
-}
-
-
-sub parse_buffer_pool_and_memory {
- parse_section(
- sub {
- m/\GBuffer pool size\s+(\d+)\n/gc && do {
- $data->{ib_bpool_size} = $1;
- return 1;
- };
- m/\GBuffer pool size, bytes\s+(\d+)\n/gc && do {
- $data->{ib_bpool_size_bytes} = $1;
- return 1;
- };
- m/\GFree buffers\s+(\d+)\n/gc && do {
- $data->{ib_bpool_free} = $1;
- return 1;
- };
- m/\GDatabase pages\s+(\d+)\n/gc && do {
- $data->{ib_bpool_dbpages} = $1;
- return 1;
- };
- m/\GModified db pages\s+(\d+)\n/gc && do {
- $data->{ib_bpool_modpages} = $1;
- return 1;
- };
- m/\GOld database pages\s+(\d+)\n/gc && do {
- $data->{ib_bpool_oldpages} = $1;
- return 1;
- };
- m/\GPages made young (\d+), not young (\d+)\n/gc && do {
- $data->{ib_bpool_made_young} = $1;
- $data->{ib_bpool_made_not_young} = $2;
- return 1;
- };
- m/\GPages read (\d+), created (\d+), written (\d+)\n/gc && do {
- $data->{ib_bpool_read} = $1;
- $data->{ib_bpool_created} = $2;
- $data->{ib_bpool_written} = $3;
- return 1;
- };
- # mariadb-5.5
- m/\GInternal hash tables \(constant factor \+ variable factor\)\n\s*Adaptive hash index\s*(\d+)\s*\((\d+) \+ (\d+)\) *\n\s+Page hash +(\d+) +\(buffer pool \d+ only\) *\n\s+Dictionary cache\s*(\d+)\s+\((\d+) \+ (\d+)\) *\n\s+File system\s+(\d+)\s+\((\d+) \+ (\d+)\) *\n\s+Lock system\s+(\d+)\s+\((\d+) \+ (\d+)\) *\n\s+Recovery system\s*(\d+)\s+\((\d+) \+ (\d+)\) *\n/gc
- && do {
- $data->{ib_bpool_internal_adaptive_hash_size_total} = $1;
- $data->{ib_bpool_internal_adaptive_hash_size_const} = $2;
- $data->{ib_bpool_internal_adaptive_hash_size_var} = $3;
- $data->{ib_bpool_internal_page_hash_size_total} = $4;
- $data->{ib_bpool_internal_dictionary_cache_size_total} = $5;
- $data->{ib_bpool_internal_dictionary_cache_size_const} = $6;
- $data->{ib_bpool_internal_dictionary_cache_size_var} = $7;
- $data->{ib_bpool_internal_file_system_size_total} = $8;
- $data->{ib_bpool_internal_file_system_size_const} = $9;
- $data->{ib_bpool_internal_file_system_size_var} = $10;
- $data->{ib_bpool_internal_lock_system_size_total} = $11;
- $data->{ib_bpool_internal_lock_system_size_const} = $12;
- $data->{ib_bpool_internal_lock_system_size_var} = $13;
- $data->{ib_bpool_internal_recovery_system_size_total} = $14;
- $data->{ib_bpool_internal_recovery_system_size_const} = $15;
- $data->{ib_bpool_internal_recovery_system_size_var} = $16;
- return 1;
- };
-
- }
- );
-}
-
-sub parse_individual_buffer_pool {
- parse_section(
- sub {
- m/\G---BUFFER POOL (\d+)\n/gc && do {
- my $pool = $1;
- $data->{ib_bpool_individual_pool_count} = $pool + 1;
- m/\GBuffer pool size\s+(\d+)\n/gc && do {
- $data->{"ib_bpool_individual_pool_${pool}_size"} = $1;
- };
- m/\GBuffer pool size, bytes\s+(\d+)\n/gc && do {
- $data->{"ib_bpool_individual_pool_${pool}_size_bytes"} = $1;
- };
- m/\GFree buffers\s+(\d+)\nDatabase pages\s+(\d+)\nOld database pages\s+(\d+)\nModified db pages\s+(\d+)\nPending reads\s+(\d+)\nPending writes: LRU\s+(\d+), flush list\s+(\d+), single page\s+(\d+)\n/gc && do {
- $data->{"ib_bpool_individual_pool_${pool}_free"} = $1;
- $data->{"ib_bpool_individual_pool_${pool}_dbpages"} = $2;
- $data->{"ib_bpool_individual_pool_${pool}_oldpages"} = $3;
- $data->{"ib_bpool_individual_pool_${pool}_modpages"} = $4;
- $data->{"ib_bpool_individual_pool_${pool}_pending_reads"} = $5;
- $data->{"ib_bpool_individual_pool_${pool}_pending_writes_lru"} = $6;
- $data->{"ib_bpool_individual_pool_${pool}_pending_writes_flush"} = $7;
- $data->{"ib_bpool_individual_pool_${pool}_pending_writes_single"} = $8;
- };
- skip_line();
- m/\GPages read (\d+), created (\d+), written (\d+)\n/gc && do {
- $data->{"ib_bpool_individual_pool_${pool}_read"} = $1;
- $data->{"ib_bpool_individual_pool_${pool}_created"} = $2;
- $data->{"ib_bpool_individual_pool_${pool}_written"} = $3;
- };
- return 1;
- };
- }
- );
-}
-
-sub handle_incomplete_innodb_status {
-
- warn "Output from SHOW ENGINE INNODB STATUS was truncated. "
- . "This happens if the output of STATUS exceeds 64KB. "
- . "Several of the InnoDB graphs might be affected by this.";
-
- # FIX Is it possible to find some of the missing values from SHOW
- # STATUS?
-}
-
-
-exit main() unless caller;
-
-
-1;
+++ /dev/null
-#!/usr/bin/env ruby
-# put in /etc/munin/plugins and restart munin-node
-# by Dan Manges, http://www.dcmanges.com/blog/rails-application-visualization-with-munin
-# NOTE: you might need to add munin to allow passwordless sudo for passenger-memory-stats
-
-require "English"
-
-def output_config
- puts <<~CONFIG
- graph_args --base 1024 -l 0 --vertical-label bytes --upper-limit 4056231936
- graph_category passenger
- graph_title Passenger memory
-
- memory.label memory
- CONFIG
- exit 0
-end
-
-def output_values
- status = `/usr/sbin/passenger-memory-stats | tail -1`
- unless $CHILD_STATUS.success?
- warn "failed executing passenger-memory-stats"
- exit 1
- end
- status =~ /(\d+\.\d+)/
- puts "memory.value #{(Regexp.last_match[1].to_f * 1024 * 1024).round}"
-end
-
-if ARGV[0] == "config"
- output_config
-else
- output_values
-end
+++ /dev/null
-#!/usr/bin/env ruby
-
-require "English"
-require "rexml/document"
-
-def passenger_status
- @passenger_status ||= REXML::Document.new(`/usr/sbin/passenger-status --show=xml`)
-end
-
-def output_config
- puts <<~CONFIG
- graph_args --lower-limit 0
- graph_category passenger
- graph_title Passenger processes
- graph_order active inactive
- graph_vlabel processes
- graph_total total
-
- active.label busy servers
- active.draw AREA
- inactive.label idle servers
- inactive.draw STACK
- CONFIG
- exit 0
-end
-
-def output_values
- active = 0
- inactive = 0
-
- passenger_status.get_elements("//process").each do |process|
- if process.text("sessions").to_i.positive?
- active += 1
- else
- inactive += 1
- end
- end
-
- puts "active.value #{active}"
- puts "inactive.value #{inactive}"
-end
-
-if ARGV[0] == "config"
- output_config
-else
- output_values
-end
+++ /dev/null
-#!/usr/bin/env ruby
-
-require "English"
-require "rexml/document"
-
-def passenger_status
- @passenger_status ||= REXML::Document.new(`/usr/sbin/passenger-status --show=xml`)
-end
-
-def output_config
- puts <<~CONFIG
- graph_args --lower-limit 0
- graph_category passenger
- graph_title Passenger queues
- graph_vlabel count
-
- global.label global
- global.draw AREA
- CONFIG
-
- groups = passenger_status.get_elements("//supergroup").map do |supergroup|
- supergroup.text("name")
- end
-
- groups.sort.each do |name|
- puts "#{name}.label #{name}"
- puts "#{name}.draw STACK"
- end
-end
-
-def output_values
- global = passenger_status.text("/item/get_wait_list").to_i
-
- puts "global.value #{global}"
-
- passenger_status.get_elements("//supergroup").each do |supergroup|
- name = supergroup.text("name")
- queue = supergroup.text("get_wait_list").to_i
-
- puts "#{name}.value #{queue}"
- end
-end
-
-if ARGV[0] == "config"
- output_config
-else
- output_values
-end
+++ /dev/null
-#!/usr/bin/env ruby
-
-require "English"
-require "rexml/document"
-
-def passenger_status
- @passenger_status ||= REXML::Document.new(`/usr/sbin/passenger-status --show=xml`)
-end
-
-def output_config
- puts <<~CONFIG
- graph_args --base 1000 --lower-limit 0
- graph_category passenger
- graph_title Passenger requests
- graph_vlabel requests / ${graph_period}
-
- total.label total
- total.type DERIVE
- total.max 1000000
- total.min 0
- CONFIG
-
- groups = passenger_status.get_elements("//supergroup").map do |supergroup|
- supergroup.text("name")
- end
-
- groups.sort.each do |name|
- puts "#{name}.label #{name}"
- puts "#{name}.type DERIVE"
- puts "#{name}.max 1000000"
- puts "#{name}.min 0"
- end
-end
-
-def output_values
- total_requests = 0
-
- passenger_status.get_elements("//supergroup").map do |supergroup|
- name = supergroup.text("name")
- requests = 0
-
- supergroup.get_elements("group/processes/process").each do |process|
- requests += process.text("processed").to_i
- end
-
- total_requests += requests
-
- puts "#{name}.value #{requests}"
- end
-
- puts "total.value #{total_requests}"
-end
-
-if ARGV[0] == "config"
- output_config
-else
- output_values
-end
+++ /dev/null
-#!/usr/bin/ruby
-
-files = [
- {
- :label => "planet",
- :name => "/store/planet/planet/planet-latest.osm.bz2",
- :title => "Planet Dump",
- :frequency => 7 * 24 * 60 * 60,
- :warning => 1.05,
- :critical => 1.1
- },
- {
- :label => "day",
- :name => "/store/planet/replication/day/state.txt",
- :title => "Daily Replication",
- :frequency => 24 * 60 * 60,
- :warning => 1.05,
- :critical => 1.1
- },
- {
- :label => "hour",
- :name => "/store/planet/replication/hour/state.txt",
- :title => "Hourly Replication",
- :frequency => 60 * 60,
- :warning => 1.05,
- :critical => 1.1
- },
- {
- :label => "minute",
- :name => "/store/planet/replication/minute/state.txt",
- :title => "Minutely Replication",
- :frequency => 60,
- :warning => 5,
- :critical => 10
- }
-]
-
-if ARGV[0] == "config"
- puts "graph_title Planet Age"
- puts "graph_args --base 1000 --lower-limit 0"
- puts "graph_scale no"
- puts "graph_vlabel fraction of expected max age"
- puts "graph_category planet"
-
- files.each do |file|
- puts "#{file[:label]}.label #{file[:title]}"
- puts "#{file[:label]}.type GAUGE"
- puts "#{file[:label]}.warning 0:#{file[:warning]}"
- puts "#{file[:label]}.critical 0:#{file[:critical]}"
- end
-else
-
- files.each do |file|
- value = (Time.now - File.mtime(file[:name])) / file[:frequency]
-
- puts "#{file[:label]}.value #{value}"
- end
-end
+++ /dev/null
-#!/usr/bin/perl
-
-use strict;
-use warnings;
-
-use Munin::Plugin::Pgsql;
-
-my $pg = Munin::Plugin::Pgsql->new(
- title => 'PostgreSQL replication delay',
- info => 'Replication delay',
- vlabel => 'Seconds',
- basequery => "SELECT (extract(epoch FROM now()) - extract(epoch FROM pg_last_xact_replay_timestamp()))::int AS delay",
- pivotquery => 1,
- configquery => "VALUES ('delay','Replication delay')",
- extraconfig => "delay.warning 300\ndelay.critical 3600",
- graphmin => 0
-);
-
-$pg->Process();
+++ /dev/null
-#!/bin/sh
-#
-# Plugin to monitor the age of the imported data in the rendering db
-#
-# Parameters:
-#
-# config (required)
-# autoconf (optional - used by munin-config)
-#
-
-if [ "$1" = "config" ]; then
-
- echo 'graph_title Data import lag'
- echo 'graph_args --base 1000 -l 0'
- echo 'graph_vlabel minutes'
- echo 'graph_category renderd'
- echo 'age.label DB import age'
- echo 'age.type GAUGE'
- echo 'age.cdef age,60,/'
- echo 'age.warning :600'
- echo 'age.critical :3600'
- exit 0
-fi
-
-tstamp=$(osmium fileinfo --extended --get=data.timestamp.last /var/lib/replicate/changes-latest.osc.gz)
-tstampsec=$(date --date=${tstamp} +%s)
-nowsec=$(date +%s)
-
-echo "age.value " `expr $nowsec - $tstampsec`
+++ /dev/null
-#!/usr/bin/perl
-# -*- cperl -*-
-
-use strict;
-use warnings;
-
-use IO::Socket::UNIX;
-
-$| = 1;
-
-my $arg = shift;
-if ($arg && $arg eq "config") {
- print "graph_title rrdcached stats\n";
- print "QueueLength.label Queue length\n";
- print "UpdatesReceived.label UpdatesReceived\n";
- print "UpdatesReceived.type DERIVE\n";
- print "FlushesReceived.label FlushesReceived\n";
- print "FlushesReceived.type DERIVE\n";
- print "UpdatesWritten.label UpdatesWritten\n";
- print "UpdatesWritten.type DERIVE\n";
- print "DataSetsWritten.label DataSetsWritten\n";
- print "DataSetsWritten.type DERIVE\n";
- print "TreeNodesNumber.label TreeNodesNumber\n";
- print "TreeDepth.label TreeDepth\n";
- print "JournalBytes.label JournalBytes\n";
- print "JournalBytes.type DERIVE\n";
- print "JournalRotate.label JournalRotate\n";
- print "JournalRotate.type DERIVE\n";
- exit 0;
-}
-
-my $sock = new IO::Socket::UNIX(
- Type => SOCK_STREAM,
- Peer => "/var/run/rrdcached.sock",
-) or die "Cannot open socket : $!";
-
-print $sock "STATS\n";
-print $sock "QUIT\n";
-
-# skip first line
-<$sock>;
-print map { s/: /.value /; $_; } <$sock>;
-
-exit 0;
+++ /dev/null
-#!/usr/bin/perl
-
-=head1 MAGIC MARKERS
-
- #%# family=snmpauto
- #%# capabilities=snmpconf
-
-=cut
-
-use strict;
-use warnings;
-use Munin::Plugin::SNMP;
-
-my $session = Munin::Plugin::SNMP->session;
-
-if (defined $ARGV[0] and $ARGV[0] eq "config") {
- my $host = $session->hostname;
- my $warning = $session->get_single(".1.3.6.1.4.1.318.1.1.26.6.1.1.6.1");
- my $critical = $session->get_single(".1.3.6.1.4.1.318.1.1.26.6.1.1.7.1");
-
- print "host_name $host\n" unless $host eq "localhost";
- print "graph_title Load\n";
- print "graph_args --base 1000 -l 0\n";
- print "graph_vlabel Amps\n";
- print "graph_category power\n";
- print "graph_info This graph shows the total throughput the PDU.\n";
-
- print "current.label Current\n";
- print "current.type GAUGE\n";
- print "current.info Current load in amps.\n";
- print "current.draw LINE2\n";
- print "current.warning ${warning}\n";
- print "current.critical ${critical}\n";
-} else {
- my $current = $session->get_single(".1.3.6.1.4.1.318.1.1.26.6.3.1.5.1");
-
- $current = $current / 10 unless $current eq "U";
-
- print "current.value ${current}\n";
-}
+++ /dev/null
-#!/usr/bin/perl
-
-=head1 MAGIC MARKERS
-
- #%# family=snmpauto
- #%# capabilities=snmpconf
-
-=cut
-
-use strict;
-use warnings;
-use Munin::Plugin::SNMP;
-
-my $session = Munin::Plugin::SNMP->session;
-
-if (defined $ARGV[0] and $ARGV[0] eq "config") {
- my $host = $session->hostname;
- my $warning = $session->get_single(".1.3.6.1.4.1.318.1.1.26.10.2.1.1.13.1");
- my $critical = $session->get_single(".1.3.6.1.4.1.318.1.1.26.10.2.1.1.14.1");
-
- print "host_name $host\n" unless $host eq "localhost";
- print "graph_title Humidity\n";
- print "graph_args -l 0\n";
- print "graph_vlabel %\n";
- print "graph_category sensors\n";
- print "graph_info This graph shows the humidity from the PDUs environmental sensor.\n";
-
- print "humidity.label Humidity\n";
- print "humidity.type GAUGE\n";
- print "humidity.info Relative humidity.\n";
- print "humidity.draw LINE2\n";
- print "humidity.warning ${warning}:\n";
- print "humidity.critical ${critical}:\n";
-} else {
- my $humidity = $session->get_single(".1.3.6.1.4.1.318.1.1.26.10.2.2.1.10.1");
-
- print "humidity.value ${humidity}\n";
-}
+++ /dev/null
-#!/usr/bin/perl
-
-=head1 MAGIC MARKERS
-
- #%# family=snmpauto
- #%# capabilities=snmpconf
-
-=cut
-
-use strict;
-use warnings;
-use Munin::Plugin::SNMP;
-
-my $session = Munin::Plugin::SNMP->session;
-
-if (defined $ARGV[0] and $ARGV[0] eq "config") {
- my $host = $session->hostname;
-
- print "host_name $host\n" unless $host eq "localhost";
- print "graph_title Power\n";
- print "graph_args --base 1000 -l 0\n";
- print "graph_vlabel Watts\n";
- print "graph_category power\n";
- print "graph_info This graph shows the power being supplied by the PDU.\n";
-
- print "power.label Power\n";
- print "power.type GAUGE\n";
- print "power.info Current power draw in watts.\n";
- print "power.draw LINE2\n";
-} else {
- my $power = $session->get_single(".1.3.6.1.4.1.318.1.1.26.6.3.1.7.1");
-
- $power = $power * 10 unless $power eq "U";
-
- print "power.value ${power}\n";
-}
+++ /dev/null
-#!/usr/bin/perl
-
-=head1 MAGIC MARKERS
-
- #%# family=snmpauto
- #%# capabilities=snmpconf
-
-=cut
-
-use strict;
-use warnings;
-use Munin::Plugin::SNMP;
-
-my $session = Munin::Plugin::SNMP->session;
-
-if (defined $ARGV[0] and $ARGV[0] eq "config") {
- my $host = $session->hostname;
- my $warning = $session->get_single(".1.3.6.1.4.1.318.1.1.26.10.2.1.1.11.1");
- my $critical = $session->get_single(".1.3.6.1.4.1.318.1.1.26.10.2.1.1.10.1");
-
- print "host_name $host\n" unless $host eq "localhost";
- print "graph_title Temperature\n";
- print "graph_args -l 0\n";
- print "graph_vlabel Degrees Celsius\n";
- print "graph_category sensors\n";
- print "graph_info This graph shows the temperature from the PDUs environmental sensor.\n";
-
- print "temperature.label Temperature\n";
- print "temperature.type GAUGE\n";
- print "temperature.info Temperature in degrees celsius.\n";
- print "temperature.draw LINE2\n";
- print "temperature.warning :${warning}\n";
- print "temperature.critical :${critical}\n";
-} else {
- my $temperature = $session->get_single(".1.3.6.1.4.1.318.1.1.26.10.2.2.1.8.1");
-
- $temperature = $temperature / 10 unless $temperature eq "U";
-
- print "temperature.value ${temperature}\n";
-}
+++ /dev/null
-#!/usr/bin/perl
-
-=head1 MAGIC MARKERS
-
- #%# family=snmpauto
- #%# capabilities=snmpconf
-
-=cut
-
-use strict;
-use warnings;
-use Munin::Plugin::SNMP;
-
-my $session = Munin::Plugin::SNMP->session;
-
-if (defined $ARGV[0] and $ARGV[0] eq "config") {
- my $host = $session->hostname;
-
- print "host_name $host\n" unless $host eq "localhost";
- print "graph_title Voltage\n";
- print "graph_args --base 1000 -l 0\n";
- print "graph_vlabel Volts\n";
- print "graph_category power\n";
- print "graph_info This graph shows the voltage being supplied by the PDU.\n";
-
- print "voltage.label Voltage\n";
- print "voltage.type GAUGE\n";
- print "voltage.info Current voltage.\n";
- print "voltage.draw LINE2\n";
-} else {
- my $voltage = $session->get_single(".1.3.6.1.4.1.318.1.1.26.6.3.1.6.1");
-
- print "voltage.value ${voltage}\n";
-}
+++ /dev/null
-#!/bin/sh
-#
-# Plugin to monitor the number of IPs being slowed down by Squid delay pools
-# This monitors the number of IPs being delayed in the last 128 pools, which
-# are the normal requests.
-#
-# Parameters:
-#
-# config (required)
-# autoconf (optional - used by munin-config)
-#
-
-if [ "$1" = "config" ]; then
-
- echo 'graph_title IPs being delayed with referer'
- echo 'graph_args --base 1000 -l 0'
- echo 'graph_vlabel IPs'
- echo 'graph_category squid'
- echo 'squid_delay1.label IPs'
- echo 'squid_delay1.min 0'
- echo 'squid_delay1.draw AREA'
-
- exit 0
-fi
-
-req0=`squidclient -h 127.0.0.1 mgr:delay|awk '\$1 == "Pool:" && \$2 < 128 { pr = 0; } \$1 == "Pool:" && \$2 >= 128 { pr = 1; } { if (pr) { print \$0; } }'|fgrep Current|egrep --count '[0-9]{1,3}:-?[0-9]{1,3} '`
-
-echo "squid_delay1.value " `expr 0 + $req0`
+++ /dev/null
-#!/bin/sh
-#
-# Plugin to monitor the number of IPs being slowed down by Squid delay pools
-# This monitors the number of IPs being delayed in the first 128 pools, which
-# are the ones which have no referer.
-#
-# Parameters:
-#
-# config (required)
-# autoconf (optional - used by munin-config)
-#
-
-if [ "$1" = "config" ]; then
-
- echo 'graph_title No-referer IPs being delayed'
- echo 'graph_args --base 1000 -l 0'
- echo 'graph_vlabel IPs'
- echo 'graph_category squid'
- echo 'squid_delay2.label IPs'
- echo 'squid_delay2.min 0'
- echo 'squid_delay2.draw AREA'
-
- exit 0
-fi
-
-req0=`squidclient -h 127.0.0.1 mgr:delay|awk '\$1 == "Pool:" && \$2 < 128 { pr = 1; } \$1 == "Pool:" && \$2 >= 128 { pr = 0; } { if (pr) { print \$0; } }'|fgrep Current|egrep --count '[0-9]{1,3}:-?[0-9]{1,3} '`
-
-echo "squid_delay2.value " `expr 0 + $req0`
+++ /dev/null
-#!/usr/bin/perl -w
-# -*- perl -*-
-
-=head1 NAME
-
-squid_icp - Plugin to graph traffic to the ICP peers
-
-=head1 CONFIGURATION
-
-The following configuration variables are used by this plugin:
-
- [squid_icp]
- env.squidhost - host (default "localhost")
- env.squidport - port (default "3128")
- env.squiduser - username (default "")
- env.squidpasswd - password (default "")
-
-=head1 ABOUT
-
-When using squid as a "load balancer" (of sorts), who gets the
-request?
-
-=head1 AUTHORS
-
-Copyright (C) 2004 Jimmy Olsen
-
-=head1 LICENSE
-
-Gnu GPLv2
-
-=begin comment
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; version 2 dated June, 1991.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-=end comment
-
-=head1 MAGIC MARKERS
-
- #%# family=manual
- #%# capabilities=autoconf
-
-=cut
-
-my $ret = undef;
-
-if (! eval "require IO::Socket;")
-{
- $ret = "IO::Socket not found";
-}
-if (! eval "require MIME::Base64;")
-{
- $ret = "MIME::Base64 not found";
-}
-if (! eval "require Net::hostent;")
-{
- $ret = "Net::hostent not found";
-}
-
-$squid_host = $ENV{squidhost} || "localhost";
-$squid_port = $ENV{squidport} || 3128;
-$user = $ENV{squiduser} || "";
-$passwd = $ENV{squidpasswd} || "";
-
-if($ARGV[0] and $ARGV[0] eq "autoconf") {
- &autoconf($squid_host, $squid_port, $user, $passwd);
-}
-
-sub autoconf {
- my ($host, $port, $user, $passwd) = @_;
-
- if ($ret)
- {
- print "no ($ret)\n";
- exit 0;
- }
-
- my $cachemgr = IO::Socket::INET->new(PeerAddr => $host,
- PeerPort => $port,
- Proto => 'tcp',
- Timeout => 5);
-
- if (!$cachemgr)
- {
- print "no (could not connect: $!)\n";
- exit 0;
- }
-
- my $request = "GET cache_object://$host/counters HTTP/1.0\r\n" .
- "Accept: */*\r\n" .
- &make_auth_header($user, $passwd) .
- "\r\n";
-
- $cachemgr->syswrite($request, length($request));
- my @lines = $cachemgr->getlines();
-
- print "yes\n";
- exit 0;
-}
-
-sub make_auth_header {
- my ($user, $passwd) = @_;
-
- if(!defined $passwd || $passwd eq "") {
- return "";
- } else {
- my $auth = MIME::Base64::encode_base64(($user ? $user : "") . ":$passwd", "");
- return "Authorization: Basic $auth\r\n" .
- "Proxy-Authorization: Basic $auth\r\n";
- }
-}
-
-
-sub query_squid {
- my ($host, $port, $user, $passwd) = @_;
- my $ret;
-
- my $cachemgr = IO::Socket::INET->new(PeerAddr => $host,
- PeerPort => $port,
- Proto => 'tcp') or die($!);
-
-
-
- my $request = "GET cache_object://$host/server_list HTTP/1.0\r\n" .
- "Accept: */*\r\n" .
- &make_auth_header($user, $passwd) .
- "\r\n";
-
- $cachemgr->syswrite($request, length($request));
- my @lines = $cachemgr->getlines();
- my $id = "";
- for(my $i = 0; $i <= $#lines; $i++) {
- chomp $lines[$i];
- if($lines[$i] =~ /Host[^:]+:\s*(\S+)\/\d+\/\d+\s*$/) {
- my $host = $1;
- $id = $host;
- $id =~ s/\./_/g;
-
- unless(exists($ret->{$id})) {
- $ret->{$id}->{host} = $host;
- $ret->{$id}->{fetches} = 0;
- }
- }
- elsif($lines[$i] =~ /FETCHES\s*:\s*(\d+)/) {
- $ret->{$id}->{fetches} += $1;
- }
- }
- return $ret;
-}
-
-my $hosts = &query_squid($squid_host, $squid_port, $user, $passwd);
-
-if($ARGV[0] and $ARGV[0] eq "config") {
- my $first = 1;
- print "graph_title Squid relay statistics\n";
- print "graph_vlabel requests / \${graph_period}\n";
- print "graph_args -l 0 --base 1000\n";
- print "graph_total total\n";
- print "graph_category squid\n";
- foreach my $i (sort keys %{$hosts}) {
- print "$i.label ", $hosts->{$i}->{host}, "\n";
- print "$i.type DERIVE\n";
- print "$i.max 500000\n";
- print "$i.min 0\n";
- if ($first) {
- print "$i.draw AREA\n";
- $first = 0;
- } else {
- print "$i.draw STACK\n";
- }
- }
- exit 0;
-}
-
-foreach my $i (keys %{$hosts}) {
- print "$i.value ", $hosts->{$i}->{fetches}, "\n";
-}
-
-# vim:syntax=perl
+++ /dev/null
-#!/bin/sh
-#
-# Copyright (C) 2008 Olivier DELHOMME. All rights reserved.
-# License GPL V2 or higher
-#
-# Abstract
-# munin plugin that logs the cache mean services times
-#
-# Authors
-# . Olivier Delhomme <olivierdelhomme at gmail dot com>
-# . Grant Slater
-#
-#%# family=auto
-#%# capabilities=autoconf
-
-if [ "$1" = "autoconf" ]; then
- SQUID_STATS=$(squidclient -h 127.0.0.1 cache_object://localhost/info)
- if [ -n "${SQUID_STATS}" ]; then
- echo yes
- exit 0
- else
- echo "no (HTTP GET failed)"
- exit 1
- fi
-fi
-
-if [ "$1" = "config" ]; then
- echo 'graph_title Squid Median Services Times'
- echo 'graph_info This graph shows the proxy median services response times.'
- echo 'graph_category squid'
- echo 'graph_args --lower-limit 0'
- echo 'graph_vlabel median reponse times (s)'
-
- echo 'mean_http.label Http'
- echo 'mean_cmis.label Cache misses'
- echo 'mean_chits.label Cache hits'
- echo 'mean_nhits.label Near hits'
- echo 'mean_nmr.label Not-modified replies'
- echo 'mean_dnsl.label Dns lookups'
- echo 'mean_icpq.label Icp queries'
-
- exit 0
-fi
-
-SQUID_TIME=$(squidclient -h 127.0.0.1 cache_object://localhost/info)
-
-SQUID_TIME_HTTP=$(echo "$SQUID_TIME" | grep "HTTP Requests (All)" | cut -d':' -f2 | sed -e "s/^\ *//" | cut -d' ' -f1)
-SQUID_TIME_CACHE_MISSES=$(echo "$SQUID_TIME" | grep "Cache Misses" | cut -d':' -f2 | sed -e "s/^\ *//" | cut -d' ' -f1)
-SQUID_TIME_CACHE_HITS=$(echo "$SQUID_TIME" | grep "Cache Hits" | cut -d':' -f2 | sed -e "s/^\ *//" | cut -d' ' -f1)
-SQUID_TIME_NEAR_HITS=$(echo "$SQUID_TIME" | grep "Near Hits" | cut -d':' -f2 | sed -e "s/^\ *//" | cut -d' ' -f1)
-SQUID_TIME_NM_REPLIES=$(echo "$SQUID_TIME" | grep "Not-Modified Replies" | cut -d':' -f2 | sed -e "s/^\ *//" | cut -d' ' -f1)
-SQUID_TIME_DNS_LOOKUPS=$(echo "$SQUID_TIME" | grep "DNS Lookups" | cut -d':' -f2 | sed -e "s/^\ *//" | cut -d' ' -f1)
-SQUID_TIME_ICP_QUERIES=$(echo "$SQUID_TIME" | grep "ICP Queries" | cut -d':' -f2 | sed -e "s/^\ *//" | cut -d' ' -f1)
-
-echo "mean_http.value $SQUID_TIME_HTTP"
-echo "mean_cmis.value $SQUID_TIME_CACHE_MISSES"
-echo "mean_chits.value $SQUID_TIME_CACHE_HITS"
-echo "mean_nhits.value $SQUID_TIME_NEAR_HITS"
-echo "mean_nmr.value $SQUID_TIME_NM_REPLIES"
-echo "mean_dnsl.value $SQUID_TIME_DNS_LOOKUPS"
-echo "mean_icpq.value $SQUID_TIME_ICP_QUERIES"
+++ /dev/null
-User-agent: *
-Disallow: /
+++ /dev/null
-class Chef
- class Munin
- def self.expand(template, nodes, separator = " ")
- nodes.map do |node|
- if node.is_a?(Hash)
- template
- .gsub(/%%%([^%]+)%%%/) { node[Regexp.last_match[1].to_sym].tr("-", "_") }
- .gsub(/%%([^%]+)%%/) { node[Regexp.last_match[1].to_sym] }
- else
- template
- .gsub("%%%", node.tr("-", "_"))
- .gsub("%%", node)
- end
- end.join(separator)
- end
- end
-end
+++ /dev/null
-#
-# Cookbook:: munin
-# Recipe:: default
-#
-# Copyright:: 2010, OpenStreetMap Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-package "munin-node"
-
-service "munin-node" do
- action [:enable, :start]
- supports :status => true, :restart => true, :reload => true
-end
-
-servers = search(:node, "recipes:munin\\:\\:server")
-
-servers.each do |server|
- server.interfaces(:role => :external) do |interface|
- firewall_rule "accept-munin-#{server}" do
- action :accept
- family interface[:family]
- source "#{interface[:zone]}:#{interface[:address]}"
- dest "fw"
- proto "tcp:syn"
- dest_ports "munin"
- source_ports "1024:"
- end
- end
-end
-
-template "/etc/munin/munin-node.conf" do
- source "munin-node.conf.erb"
- owner "root"
- group "root"
- mode "644"
- variables :servers => servers
- notifies :restart, "service[munin-node]"
-end
+++ /dev/null
-#
-# Cookbook:: munin
-# Recipe:: default
-#
-# Copyright:: 2010, OpenStreetMap Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-include_recipe "munin"
-
-remote_directory "/usr/local/share/munin/plugins" do
- source "plugins"
- owner "root"
- group "root"
- mode "755"
- files_owner "root"
- files_group "root"
- files_mode "755"
- purge true
-end
-
-remote_directory "/etc/munin/plugin-conf.d" do
- source "plugin-conf.d"
- owner "root"
- group "munin"
- mode "750"
- files_owner "root"
- files_group "root"
- files_mode "644"
- purge false
- notifies :restart, "service[munin-node]"
-end
-
-if Dir.glob("/proc/acpi/thermal_zone/*/temperature").empty?
- munin_plugin "acpi" do
- action :delete
- end
-else
- munin_plugin "acpi"
-end
-
-# apcpdu_
-munin_plugin "cpu"
-
-if File.exist?("/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state")
- munin_plugin "cpuspeed"
-else
- munin_plugin "cpuspeed" do
- action :delete
- end
-end
-
-munin_plugin_conf "df" do
- template "df.erb"
-end
-
-munin_plugin "df"
-munin_plugin "df_inode"
-
-munin_plugin_conf "diskstats" do
- template "diskstats.erb"
-end
-
-munin_plugin "diskstats"
-munin_plugin "entropy"
-munin_plugin "forks"
-
-if node[:kernel][:modules].include?("nf_conntrack")
- package "conntrack"
-
- munin_plugin "fw_conntrack"
- munin_plugin "fw_forwarded_local"
-else
- munin_plugin "fw_conntrack" do
- action :delete
- end
-
- munin_plugin "fw_forwarded_local" do
- action :delete
- end
-end
-
-if File.read("/proc/sys/net/ipv4/ip_forward").chomp == "1"
- munin_plugin "fw_packets"
-else
- munin_plugin "fw_packets" do
- action :delete
- end
-end
-
-if File.exist?("/sbin/hpasmcli")
- munin_plugin "hpasmcli2_temp" do
- target "hpasmcli2_"
- end
-
- munin_plugin "hpasmcli2_fans" do
- target "hpasmcli2_"
- end
-else
- munin_plugin "hpasmcli2_temp" do
- action :delete
- end
-
- munin_plugin "hpasmcli2_fans" do
- action :delete
- end
-end
-
-munin_plugin "hpasmcli_temp" do
- action :delete
-end
-
-munin_plugin "hpasmcli_fans" do
- action :delete
-end
-
-munin_plugin "http_loadtime" do
- action :delete
-end
-
-node[:network][:interfaces].each do |ifname, ifattr|
- if ifattr[:flags]&.include?("UP") && !ifattr[:flags].include?("LOOPBACK")
- if node[:hardware] &&
- node[:hardware][:network] &&
- node[:hardware][:network][ifname][:device] =~ /^virtio/
- munin_plugin_conf "if_#{ifname}" do
- template "if.erb"
- variables :ifname => ifname
- end
- else
- munin_plugin_conf "if_#{ifname}" do
- action :delete
- end
- end
-
- munin_plugin "if_err_#{ifname}" do
- target "if_err_"
- end
-
- munin_plugin "if_#{ifname}" do
- target "if_"
- end
- else
- munin_plugin "if_err_#{ifname}" do
- action :delete
- end
-
- munin_plugin "if_#{ifname}" do
- action :delete
- end
- end
-end
-
-munin_plugin "interrupts"
-munin_plugin "iostat"
-munin_plugin "iostat_ios"
-
-if Dir.glob("/dev/ipmi*").empty?
- munin_plugin_conf "ipmi" do
- action :delete
- end
-
- munin_plugin "ipmi_fans" do
- action :delete
- end
-
- munin_plugin "ipmi_temp" do
- action :delete
- end
-
- munin_plugin "ipmi_power" do
- action :delete
- end
-else
- munin_plugin_conf "ipmi" do
- template "ipmi.erb"
- end
-
- munin_plugin "ipmi_fans" do
- target "ipmi_"
- end
-
- munin_plugin "ipmi_temp" do
- target "ipmi_"
- end
-
- munin_plugin "ipmi_power" do
- target "ipmi_"
- end
-end
-
-munin_plugin "irqstats"
-munin_plugin "load"
-munin_plugin "memory"
-munin_plugin "netstat"
-
-if node[:kernel][:modules].include?("nfsv3")
- munin_plugin "nfs_client"
-else
- munin_plugin "nfs_client" do
- action :delete
- end
-end
-
-if node[:kernel][:modules].include?("nfsv4")
- munin_plugin "nfs4_client"
-else
- munin_plugin "nfs4_client" do
- action :delete
- end
-end
-
-if node[:kernel][:modules].include?("nfsd")
- munin_plugin "nfsd"
- munin_plugin "nfsd4"
-else
- munin_plugin "nfsd" do
- action :delete
- end
-
- munin_plugin "nfsd4" do
- action :delete
- end
-end
-
-munin_plugin "open_files"
-munin_plugin "open_inodes"
-
-munin_plugin "postfix_mailqueue" do
- action :delete
-end
-
-munin_plugin "postfix_mailvolume" do
- action :delete
-end
-
-munin_plugin "processes"
-munin_plugin "proc_pri"
-
-sensors_fan = false
-sensors_temp = false
-sensors_volt = false
-
-Dir.glob("/sys/class/hwmon/hwmon*").each do |hwmon|
- hwmon = "#{hwmon}/device" unless File.exist?("#{hwmon}/name")
-
- sensors_fan = true unless Dir.glob("#{hwmon}/fan*_input").empty?
- sensors_temp = true unless Dir.glob("#{hwmon}/temp*_input").empty?
- sensors_volt = true unless Dir.glob("#{hwmon}/in*_input").empty?
-end
-
-package "lm-sensors" if sensors_fan || sensors_temp || sensors_volt
-
-if sensors_fan
- munin_plugin "sensors_fan" do
- target "sensors_"
- end
-else
- munin_plugin "sensors_fan" do
- action :delete
- end
-end
-
-if sensors_temp
- munin_plugin "sensors_temp" do
- target "sensors_"
- end
-else
- munin_plugin "sensors_temp" do
- action :delete
- end
-end
-
-if sensors_volt
- munin_plugin "sensors_volt" do
- target "sensors_"
- conf "sensors_volt.erb"
- end
-else
- munin_plugin "sensors_volt" do
- action :delete
- end
-end
-
-munin_plugin "swap"
-munin_plugin "tcp"
-munin_plugin "threads"
-munin_plugin "uptime"
-munin_plugin "users"
-munin_plugin "vmstat"
+++ /dev/null
-#
-# Cookbook:: munin
-# Recipe:: server
-#
-# Copyright:: 2010, OpenStreetMap Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-include_recipe "apache"
-
-package "munin"
-package "rrdcached"
-package "libcgi-fast-perl"
-
-template "/etc/default/rrdcached" do
- source "rrdcached.erb"
- owner "root"
- group "root"
- mode "644"
-end
-
-directory "/var/lib/munin/rrdcached" do
- owner "munin"
- group "munin"
- mode "755"
-end
-
-service "rrdcached" do
- action [:enable, :start]
- subscribes :restart, "template[/etc/default/rrdcached]"
-end
-
-munin_plugin "rrdcached"
-
-expiry_time = 14 * 86400
-
-clients = search(:node, "recipes:munin\\:\\:default").sort_by(&:name)
-frontends = search(:node, "recipes:web\\:\\:frontend").reject { |n| Time.now - Time.at(n[:ohai_time]) > expiry_time }.sort_by(&:name).map do |n|
- { :name => n.name.split(".").first, :interface => n.interfaces(:role => :external).first[:interface].tr(".", "_") }
-end
-tilecaches = search(:node, "roles:tilecache").reject { |n| Time.now - Time.at(n[:ohai_time]) > expiry_time }.sort_by(&:name).map do |n|
- { :name => n.name.split(".").first, :interface => n.interfaces(:role => :external).first[:interface].tr(".", "_") }
-end
-renderers = search(:node, "roles:tile").reject { |n| Time.now - Time.at(n[:ohai_time]) > expiry_time }.sort_by(&:name).map do |n|
- { :name => n.name.split(".").first, :interface => n.interfaces(:role => :external).first[:interface].tr(".", "_") }
-end
-geocoders = search(:node, "roles:nominatim").reject { |n| Time.now - Time.at(n[:ohai_time]) > expiry_time }.sort_by(&:name).map do |n|
- { :name => n.name.split(".").first, :interface => n.interfaces(:role => :external).first[:interface].tr(".", "_") }
-end
-
-template "/etc/munin/munin.conf" do
- source "munin.conf.erb"
- owner "root"
- group "root"
- mode "644"
- variables :expiry_time => expiry_time, :clients => clients,
- :frontends => frontends, :geocoders => geocoders,
- :tilecaches => tilecaches, :renderers => renderers
-end
-
-apache_module "fcgid"
-apache_module "rewrite"
-apache_module "headers"
-
-remote_directory "/srv/munin.openstreetmap.org" do
- source "www"
- owner "root"
- group "root"
- mode "755"
- files_owner "root"
- files_group "root"
- files_mode "644"
-end
-
-# directory to put dumped files in
-directory "/srv/munin.openstreetmap.org/dumps" do
- owner "www-data"
- group "www-data"
- mode "755"
-end
-
-ssl_certificate "munin.openstreetmap.org" do
- domains ["munin.openstreetmap.org", "munin.osm.org"]
- notifies :reload, "service[apache2]"
-end
-
-apache_site "munin.openstreetmap.org" do
- template "apache.erb"
-end
-
-template "/etc/cron.daily/munin-backup" do
- source "backup.cron.erb"
- owner "root"
- group "root"
- mode "755"
-end
-
-munin_plugin "munin_stats"
-munin_plugin "munin_update"
-munin_plugin "munin_rrdcached"
+++ /dev/null
-#
-# Cookbook:: munin
-# Provider:: munin_plugin
-#
-# Copyright:: 2013, OpenStreetMap Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-unified_mode true
-
-default_action :create
-
-property :plugin, :kind_of => String, :name_property => true
-property :target, :kind_of => String
-property :conf, :kind_of => String
-property :conf_cookbook, :kind_of => String
-property :conf_variables, :kind_of => Hash, :default => {}
-property :restart_munin, :kind_of => [TrueClass, FalseClass], :default => true
-
-action :create do
- link_action = case target_path
- when nil then :delete
- else :create
- end
-
- link plugin_path do
- action link_action
- to target_path
- end
-
- if new_resource.conf
- munin_plugin_conf new_resource.plugin do
- cookbook new_resource.conf_cookbook
- template new_resource.conf
- variables new_resource.conf_variables
- restart_munin false
- end
- end
-end
-
-action :delete do
- link plugin_path do
- action :delete
- end
-
- if new_resource.conf
- munin_plugin_conf new_resource.plugin do
- action :delete
- restart_munin false
- end
- end
-end
-
-action_class do
- def plugin_path
- "/etc/munin/plugins/#{new_resource.plugin}"
- end
-
- def target_path
- if ::File.exist?(target)
- target
- elsif ::File.exist?("/usr/local/share/munin/plugins/#{target}")
- "/usr/local/share/munin/plugins/#{target}"
- elsif ::File.exist?("/usr/share/munin/plugins/#{target}")
- "/usr/share/munin/plugins/#{target}"
- end
- end
-
- def target
- new_resource.target || new_resource.plugin
- end
-end
-
-def after_created
- notifies :restart, "service[munin-node]" if restart_munin
-end
+++ /dev/null
-#
-# Cookbook:: munin
-# Resource:: munin_plugin_conf
-#
-# Copyright:: 2013, OpenStreetMap Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-unified_mode true
-
-default_action :create
-
-property :plugin_conf, :kind_of => String, :name_property => true
-property :cookbook, :kind_of => [String, nil]
-property :template, :kind_of => String, :required => [:create]
-property :variables, :kind_of => Hash, :default => {}
-property :restart_munin, :kind_of => [TrueClass, FalseClass], :default => true
-
-action :create do
- declare_resource :template, config_file do
- cookbook new_resource.cookbook
- source new_resource.template
- owner "root"
- group "root"
- mode "644"
- variables new_resource.variables.merge(:name => new_resource.plugin_conf)
- end
-end
-
-action :delete do
- file config_file do
- action :delete
- end
-end
-
-action_class do
- def config_file
- "/etc/munin/plugin-conf.d/#{new_resource.plugin_conf}"
- end
-end
-
-def after_created
- notifies :restart, "service[munin-node]" if restart_munin
-end
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-<VirtualHost *:443>
- ServerName munin.openstreetmap.org
- ServerAlias munin.osm.org
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/munin.openstreetmap.org-access.log combined
- ErrorLog /var/log/apache2/munin.openstreetmap.org-error.log
-
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/munin.openstreetmap.org.pem
- SSLCertificateKeyFile /etc/ssl/private/munin.openstreetmap.org.key
-
- SetEnv RRDCACHED_ADDRESS /var/run/rrdcached.sock
-
- DocumentRoot /srv/munin.openstreetmap.org
- Alias /static/favicon.ico /srv/munin.openstreetmap.org/favicon.ico
- Alias /static/ /etc/munin/static/
- ScriptAlias /munin-cgi/ /usr/lib/munin/cgi/
-
- # Remove Proxy request header to mitigate https://httpoxy.org/
- RequestHeader unset Proxy early
-
- RewriteEngine on
- RewriteCond %{REQUEST_URI} !^/static/
- RewriteCond %{REQUEST_URI} !^/dumps/
- RewriteRule ^(/.*\.html)?$ /munin-cgi/munin-cgi-html/$1 [PT]
-</VirtualHost>
-
-<VirtualHost *:80>
- ServerName munin.openstreetmap.org
- ServerAlias munin.osm.org
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/munin.openstreetmap.org-access.log combined
- ErrorLog /var/log/apache2/munin.openstreetmap.org-error.log
-
- RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
- RedirectPermanent / https://munin.openstreetmap.org/
-</VirtualHost>
-
-<Directory /srv/munin.openstreetmap.org>
- Require all granted
-</Directory>
-
-<Directory /srv/munin.openstreetmap.org/dumps>
- Options +Indexes
-</Directory>
-
-<Directory /etc/munin/static>
- Require all granted
-</Directory>
-
-<Directory /usr/lib/munin/cgi>
- Options +ExecCGI
- SetHandler fcgid-script
- Require all granted
-</Directory>
+++ /dev/null
-#!/bin/sh
-
-# DO NOT EDIT - This file is being maintained by Chef
-
-T=$(mktemp -d -t -p /var/tmp munin.XXXXXXXXXX)
-D=$(date +%Y-%m-%d)
-B=munin-$D.tar.gz
-
-mkdir $T/munin-$D
-ln -s /var/lib/munin/openstreetmap $T/munin-$D
-ln -s /var/lib/munin/*.storable $T/munin-$D
-
-export RSYNC_RSH="ssh -ax"
-
-nice tar --create --dereference --directory=$T --warning=no-file-removed munin-$D | nice gzip --rsyncable -9 > $T/$B
-nice rsync --preallocate --fuzzy $T/$B backup::backup
-
-rm -rf $T
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-# Configure logging
-log_level 4
-log_file /var/log/munin/munin-node.log
-pid_file /var/run/munin/munin-node.pid
-
-# Run in the background
-background 1
-setsid 1
-
-# Run as root
-user root
-group root
-
-# Regexps for files to ignore
-ignore_file ~$
-ignore_file DEADJOE$
-ignore_file \.bak$
-ignore_file %$
-ignore_file \.dpkg-(tmp|new|old|dist)$
-ignore_file \.rpm(save|new)$
-ignore_file \.pod$
-
-# Set the hostname
-host_name <%= node.name %>
-
-# List on port 4949 on all interfaces
-host *
-port 4949
-
-# List the addresses that are allowed to connect
-allow ^127\.0\.0\.1$
-<% @servers.each do |server| -%>
-<% server.interfaces do |interface| -%>
-allow ^<%= Regexp.quote(interface[:address]) %>$
-<% end -%>
-<% end -%>
-<% node[:munin][:allow].each do |address| -%>
-allow ^<%= Regexp.quote(address) %>$
-<% end -%>
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-# Set maximum number of update processes to run at once
-max_processes 64
-
-# Maximum number of graphs to generate at once
-max_graph_jobs 24
-max_cgi_graph_jobs 24
-
-# Render pages and graphs on demand
-html_strategy cgi
-graph_strategy cgi
-
-# Use rrdcached
-rrdcached_socket /var/run/rrdcached.sock
-
-# Configure alert targets
-contact.admins.command mail -s "Munin Notification for ${var:host}" admins@openstreetmap.org
-contact.admins.always_send invalid
-contact.null.command cat > /dev/null
-contact.null.always_send invalid
-
-# Send alerts to the admins by default
-contacts admins
-
-# Ignore uncontactable hosts for twelve hours
-unknown_limit 144
-<% @clients.sort { |a,b| a.name <=> b.name }.each do |client| -%>
-
-# Configure monitoring for <%= client.name %>
-[<%= client.name %>]
-<% if Time.now - Time.at(client[:ohai_time]) > @expiry_time -%>
- update no
-<% end -%>
-<% if client[:networking][:roles][:external][:zone] == "ucl" -%>
- address <%= client.internal_ipaddress || client.external_ipaddress %>
-<% elsif client[:networking][:roles][:external][:zone] == "ams" -%>
- address <%= client.internal_ipaddress || client.external_ipaddress %>
-<% elsif client[:networking][:roles][:external][:zone] == "bm" -%>
- address <%= client.internal_ipaddress || client.external_ipaddress %>
-<% elsif client.external_ipaddress -%>
- address <%= client.external_ipaddress %>
-<% end -%>
- use_node_name yes
-<% if client[:munin][:plugins] -%>
-<% client[:munin][:plugins].keys.sort.each do |plugin| -%>
-<% client[:munin][:plugins][plugin].keys.sort.each do |value| -%>
-<% if client[:munin][:plugins][plugin][value].kind_of?(Hash) -%>
-<% if client[:munin][:plugins][plugin][value][:graph] -%>
- <%= plugin %>.<%= value %>.graph <%= client[:munin][:plugins][plugin][value][:graph] %>
-<% end -%>
-<% if client[:munin][:plugins][plugin][value][:draw] -%>
- <%= plugin %>.<%= value %>.draw <%= client[:munin][:plugins][plugin][value][:draw] %>
-<% end -%>
-<% if client[:munin][:plugins][plugin][value][:label] -%>
- <%= plugin %>.<%= value %>.label <%= client[:munin][:plugins][plugin][value][:label] %>
-<% end -%>
-<% if client[:munin][:plugins][plugin][value][:warning] -%>
- <%= plugin %>.<%= value %>.warning <%= client[:munin][:plugins][plugin][value][:warning] %>
-<% end -%>
-<% if client[:munin][:plugins][plugin][value][:critical] -%>
- <%= plugin %>.<%= value %>.critical <%= client[:munin][:plugins][plugin][value][:critical] %>
-<% end -%>
-<% else -%>
- <%= plugin %>.<%= value %> <%= client[:munin][:plugins][plugin][value] %>
-<% end -%>
-<% end -%>
-<% end -%>
-<% end -%>
-<% if client[:munin][:graphs] -%>
-<% client[:munin][:graphs].keys.sort.each do |graph| -%>
-<% if client[:munin][:graphs][graph][:title] -%>
- <%= graph %>.graph_title <%= client[:munin][:graphs][graph][:title] %>
-<% end -%>
-<% if client[:munin][:graphs][graph][:vlabel] -%>
- <%= graph %>.graph_vlabel <%= client[:munin][:graphs][graph][:vlabel] %>
-<% end -%>
-<% if client[:munin][:graphs][graph][:category] -%>
- <%= graph %>.graph_category <%= client[:munin][:graphs][graph][:category] %>
-<% end -%>
-<% client[:munin][:graphs][graph][:values].keys.sort.each do |value| -%>
-<% if client[:munin][:graphs][graph][:values][value][:sum] -%>
- <%= graph %>.<%= value %>.sum <%= client[:munin][:graphs][graph][:values][value][:sum].join(" ") %>
-<% end -%>
-<% if client[:munin][:graphs][graph][:values][value][:label] -%>
- <%= graph %>.<%= value %>.label <%= client[:munin][:graphs][graph][:values][value][:label] %>
-<% end -%>
-<% end -%>
-<% end -%>
-<% end -%>
-<% end -%>
-
-# Configure monitoring for switch1.openstreetmap.org
-[openstreetmap.org;switch1.openstreetmap.org]
- address 10.0.48.10
- use_node_name no
-
-# Configure monitoring for pdu1.ams.openstreetmap.org
-[openstreetmap.org;pdu1.ams.openstreetmap.org]
- address 10.0.48.10
- use_node_name no
-
-# Configure monitoring for pdu1.ams.openstreetmap.org
-[openstreetmap.org;pdu2.ams.openstreetmap.org]
- address 10.0.48.10
- use_node_name no
-
-# Configure compound graphs for ams.openstreetmap.org
-[ams.openstreetmap.org]
- update no
- apcpdu_current.graph_title Load
- apcpdu_current.graph_args --lower-limit 0
- apcpdu_current.graph_vlabel Amps
- apcpdu_current.graph_category power
- apcpdu_current.graph_order pdu1=pdu1.ams.openstreetmap.org:snmp_pdu1_ams_openstreetmap_org_apcpdu_current.current pdu2=pdu2.ams.openstreetmap.org:snmp_pdu2_ams_openstreetmap_org_apcpdu_current.current
- apcpdu_current.graph_total total
- apcpdu_current.pdu1.label PDU A
- apcpdu_current.pdu1.draw AREASTACK
- apcpdu_current.pdu1.min 0
- apcpdu_current.pdu2.label PDU B
- apcpdu_current.pdu2.draw AREASTACK
- apcpdu_current.pdu2.min 0
- apcpdu_power.graph_title Power
- apcpdu_power.graph_args --base 1000 --lower-limit 0
- apcpdu_power.graph_vlabel Watts
- apcpdu_power.graph_category power
- apcpdu_power.graph_order pdu1=pdu1.ams.openstreetmap.org:snmp_pdu1_ams_openstreetmap_org_apcpdu_power.power pdu2=pdu2.ams.openstreetmap.org:snmp_pdu2_ams_openstreetmap_org_apcpdu_power.power
- apcpdu_power.graph_total total
- apcpdu_power.pdu1.label PDU A
- apcpdu_power.pdu1.draw AREASTACK
- apcpdu_power.pdu1.min 0
- apcpdu_power.pdu2.label PDU B
- apcpdu_power.pdu2.draw AREASTACK
- apcpdu_power.pdu2.min 0
- apcpdu_temperature.graph_title Temperature
- apcpdu_temperature.graph_args --lower-limit 0
- apcpdu_temperature.graph_vlabel Degrees Celsius
- apcpdu_temperature.graph_category sensors
- apcpdu_temperature.graph_order temperature=pdu1.ams.openstreetmap.org:snmp_pdu1_ams_openstreetmap_org_apcpdu_temperature.temperature
- apcpdu_temperature.temperature.label Temperature
- apcpdu_temperature.temperature.draw LINE2
- apcpdu_temperature.temperature.min 0
- apcpdu_humidity.graph_title Humidity
- apcpdu_humidity.graph_args --lower-limit 0
- apcpdu_humidity.graph_vlabel %
- apcpdu_humidity.graph_category sensors
- apcpdu_humidity.graph_order humidity=pdu1.ams.openstreetmap.org:snmp_pdu1_ams_openstreetmap_org_apcpdu_humidity.humidity
- apcpdu_humidity.humidity.label Humidity
- apcpdu_humidity.humidity.draw LINE2
- apcpdu_humidity.humidity.min 0
-<% unless @frontends.empty? -%>
-
-# Configure compound graphs for www.openstreetmap.org
-[www.openstreetmap.org]
- update no
- apache_accesses.graph_title Apache accesses
- apache_accesses.graph_vlabel accesses / ${graph_period}
- apache_accesses.graph_category apache
- apache_accesses.graph_args --lower-limit 0
- apache_accesses.accesses80.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:apache_accesses.accesses80", @frontends %>
- apache_accesses.accesses80.label port 80
- apache_accesses.accesses80.min 0
- apache_volume.graph_title Apache volume
- apache_volume.graph_vlabel bytes per ${graph_period}
- apache_volume.graph_category apache
- apache_volume.graph_args --lower-limit 0
- apache_volume.volume80.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:apache_volume.volume80", @frontends %>
- apache_volume.volume80.label port 80
- apache_volume.volume80.min 0
- network_in.graph_title Inbound network traffic
- network_in.graph_vlabel bits in per ${graph_period}
- network_in.graph_category network
- network_in.graph_order <%= Chef::Munin.expand "%%%name%%%=%%name%%.openstreetmap.org:if_%%interface%%.down", @frontends %>
- network_in.graph_total total
- network_in.graph_args --lower-limit 0
-<% @frontends.each do |fe| -%>
- network_in.<%= fe[:name].tr("-", "_") %>.label <%= fe[:name] %>
- network_in.<%= fe[:name].tr("-", "_") %>.cdef <%= fe[:name].tr("-", "_") %>,8,*
- network_in.<%= fe[:name].tr("-", "_") %>.draw AREASTACK
- network_in.<%= fe[:name].tr("-", "_") %>.min 0
-<% end -%>
- network_out.graph_title Outbound network traffic
- network_out.graph_vlabel bits out per ${graph_period}
- network_out.graph_category network
- network_out.graph_order <%= Chef::Munin.expand "%%%name%%%=%%name%%.openstreetmap.org:if_%%interface%%.up", @frontends %>
- network_out.graph_total total
- network_out.graph_args --lower-limit 0
-<% @frontends.each do |fe| -%>
- network_out.<%= fe[:name].tr("-", "_") %>.label <%= fe[:name] %>
- network_out.<%= fe[:name].tr("-", "_") %>.cdef <%= fe[:name].tr("-", "_") %>,8,*
- network_out.<%= fe[:name].tr("-", "_") %>.draw AREASTACK
- network_out.<%= fe[:name].tr("-", "_") %>.min 0
-<% end -%>
- api_calls_www.graph_title Active requests
- api_calls_www.graph_vlabel Number of requests
- api_calls_www.graph_category api
- api_calls_www.graph_order map upload amf history full trkpts web other
- api_calls_www.web.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_%%%name%%%.web", @frontends %>
- api_calls_www.web.label Web site traffic
- api_calls_www.upload.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_%%%name%%%.upload", @frontends %>
- api_calls_www.upload.label Changeset diff uploads
- api_calls_www.other.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_%%%name%%%.other", @frontends %>
- api_calls_www.other.label Other API calls
- api_calls_www.amf.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_%%%name%%%.amf", @frontends %>
- api_calls_www.amf.label AMF API calls
- api_calls_www.history.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_%%%name%%%.history", @frontends %>
- api_calls_www.history.label Element history fetches
- api_calls_www.full.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_%%%name%%%.full", @frontends %>
- api_calls_www.full.label Full element fetches
- api_calls_www.map.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_%%%name%%%.map", @frontends %>
- api_calls_www.map.label Map API calls
- api_calls_www.trkpts.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_%%%name%%%.trkpts", @frontends %>
- api_calls_www.trkpts.label GPX trackpoints calls
- api_calls_error.graph_title HTTP errors
- api_calls_error.graph_vlabel Number of errors per ${graph_period}
- api_calls_error.graph_category api
- api_calls_error.graph_order http401 http422 http500 http502 http503 http509
- api_calls_error.http401.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_status.http401", @frontends %>
- api_calls_error.http401.label 401 Unauthorized
- api_calls_error.http401.warning :0.5
- api_calls_error.http422.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_status.http422", @frontends %>
- api_calls_error.http422.label 422 Unprocessable Entity
- api_calls_error.http422.warning :0.5
- api_calls_error.http500.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_status.http500", @frontends %>
- api_calls_error.http500.label 500 Internal Server Error
- api_calls_error.http500.warning :0.5
- api_calls_error.http502.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_status.http502", @frontends %>
- api_calls_error.http502.label 502 Bad Gateway
- api_calls_error.http502.warning :0.5
- api_calls_error.http503.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_status.http503", @frontends %>
- api_calls_error.http503.label 503 Service Unavailable
- api_calls_error.http503.warning :0.5
- api_calls_error.http509.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_status.http509", @frontends %>
- api_calls_error.http509.label 509 Bandwidth Limit Exceeded
- api_calls_error.http509.warning :5
- api_calls_num.graph_title Requests processed
- api_calls_num.graph_vlabel Number of requests per ${graph_period}
- api_calls_num.graph_category api
- api_calls_num.graph_order map upload amf history full trkpts web other
- api_calls_num.web.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_num.web", @frontends %>
- api_calls_num.web.label Web site traffic
- api_calls_num.upload.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_num.upload", @frontends %>
- api_calls_num.upload.label Changeset diff uploads
- api_calls_num.other.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_num.other", @frontends %>
- api_calls_num.other.label Other API calls
- api_calls_num.amf.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_num.amf", @frontends %>
- api_calls_num.amf.label AMF API calls
- api_calls_num.history.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_num.history", @frontends %>
- api_calls_num.history.label Element history fetches
- api_calls_num.full.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_num.full", @frontends %>
- api_calls_num.full.label Full element fetches
- api_calls_num.map.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_num.map", @frontends %>
- api_calls_num.map.label Map API calls
- api_calls_num.trkpts.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_num.trkpts", @frontends %>
- api_calls_num.trkpts.label GPX trackpoints calls
- api_waits_www.graph_title Wait times for active requests
- api_waits_www.graph_vlabel Average time of requests
- api_waits_www.graph_category api
- api_waits_www.graph_order map upload amf history full trkpts web other
- api_waits_www.web.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_waits_%%%name%%%.web", @frontends %>
- api_waits_www.web.label Web site traffic
- api_waits_www.web.cdef web,2,/
- api_waits_www.upload.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_waits_%%%name%%%.upload", @frontends %>
- api_waits_www.upload.label Changeset diff uploads
- api_waits_www.upload.cdef upload,2,/
- api_waits_www.other.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_waits_%%%name%%%.other", @frontends %>
- api_waits_www.other.label Other API calls
- api_waits_www.other.cdef other,2,/
- api_waits_www.amf.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_waits_%%%name%%%.amf", @frontends %>
- api_waits_www.amf.label AMF API calls
- api_waits_www.amf.cdef amf,2,/
- api_waits_www.history.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_waits_%%%name%%%.history", @frontends %>
- api_waits_www.history.label Element history fetches
- api_waits_www.history.cdef history,2,/
- api_waits_www.full.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_waits_%%%name%%%.full", @frontends %>
- api_waits_www.full.label Full element fetches
- api_waits_www.full.cdef full,2,/
- api_waits_www.map.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_waits_%%%name%%%.map", @frontends %>
- api_waits_www.map.label Map API calls
- api_waits_www.map.cdef map,2,/
- api_waits_www.trkpts.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_waits_%%%name%%%.trkpts", @frontends %>
- api_waits_www.trkpts.label GPX trackpoints calls
- api_waits_www.trkpts.cdef trkpts,2,/
- memcached_multi_commands.graph_title Commands
- memcached_multi_commands.graph_vlabel Commands per ${graph_period}
- memcached_multi_commands.graph_category memcached
- memcached_multi_commands.graph_order cmd_get cmd_set cmd_touch get_hits get_misses delete_hits delete_misses incr_hits incr_misses decr_hits decr_misses touch_hits touch_misses
- memcached_multi_commands.cmd_get.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.cmd_get", @frontends %>
- memcached_multi_commands.cmd_get.label Gets
- memcached_multi_commands.cmd_set.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.cmd_set", @frontends %>
- memcached_multi_commands.cmd_set.label Sets
- memcached_multi_commands.cmd_touch.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.cmd_touch", @frontends %>
- memcached_multi_commands.cmd_touch.label Touches
- memcached_multi_commands.get_hits.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.get_hits", @frontends %>
- memcached_multi_commands.get_hits.label Get Hits
- memcached_multi_commands.get_misses.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.get_misses", @frontends %>
- memcached_multi_commands.get_misses.label Get Misses
- memcached_multi_commands.delete_hits.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.delete_hits", @frontends %>
- memcached_multi_commands.delete_hits.label Delete Hits
- memcached_multi_commands.delete_misses.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.delete_misses", @frontends %>
- memcached_multi_commands.delete_misses.label Delete Misses
- memcached_multi_commands.incr_hits.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.incr_hits", @frontends %>
- memcached_multi_commands.incr_hits.label Increment Hits
- memcached_multi_commands.incr_misses.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.incr_misses", @frontends %>
- memcached_multi_commands.incr_misses.label Increment Misses
- memcached_multi_commands.decr_hits.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.decr_hits", @frontends %>
- memcached_multi_commands.decr_hits.label Decrement Hits
- memcached_multi_commands.decr_misses.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.decr_misses", @frontends %>
- memcached_multi_commands.decr_misses.label Decrement Misses
- memcached_multi_commands.touch_hits.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.touch_hits", @frontends %>
- memcached_multi_commands.touch_hits.label Touch Hits
- memcached_multi_commands.touch_misses.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.touch_misses", @frontends %>
- memcached_multi_commands.touch_misses.label Touch Misses
- memcached_multi_conns.graph_title Connections
- memcached_multi_conns.graph_vlabel Connections per ${graph_period}
- memcached_multi_conns.graph_category memcached
- memcached_multi_conns.graph_order max_conns curr_conns avg_conns
- memcached_multi_conns.curr_conns.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_conns.curr_conns", @frontends %>
- memcached_multi_conns.curr_conns.label Current Connections
- memcached_multi_conns.max_conns.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_conns.max_conns", @frontends %>
- memcached_multi_conns.max_conns.label Max Connections
- memcached_multi_conns.avg_conns.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_conns.avg_conns", @frontends %>
- memcached_multi_conns.avg_conns.label Avg Connections
- memcached_multi_evictions.graph_title Evictions
- memcached_multi_evictions.graph_vlabel Evictions per ${graph_period}
- memcached_multi_evictions.graph_category memcached
- memcached_multi_evictions.evictions.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_evictions.evictions", @frontends %>
- memcached_multi_evictions.evictions.label Evictions
- memcached_multi_evictions.evicted_nonzero.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_evictions.evicted_nonzero", @frontends %>
- memcached_multi_evictions.evicted_nonzero.label Evictions prior to Expire
- memcached_multi_evictions.reclaimed.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_evictions.reclaimed", @frontends %>
- memcached_multi_evictions.reclaimed.label Reclaimed Items
- memcached_multi_items.graph_title Items
- memcached_multi_items.graph_vlabel Items in Memcached
- memcached_multi_items.graph_category memcached
- memcached_multi_items.graph_order curr_items total_items
- memcached_multi_items.curr_items.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_items.curr_items", @frontends %>
- memcached_multi_items.curr_items.label Current Items
- memcached_multi_items.total_items.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_items.total_items", @frontends %>
- memcached_multi_items.total_items.label New Items
- memcached_multi_memory.graph_title Memory Usage
- memcached_multi_memory.graph_vlabel Bytes Used
- memcached_multi_memory.graph_category memcached
- memcached_multi_memory.graph_order limit_maxbytes bytes
- memcached_multi_memory.limit_maxbytes.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_memory.limit_maxbytes", @frontends %>
- memcached_multi_memory.limit_maxbytes.label Maximum Bytes Allocated
- memcached_multi_memory.bytes.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_memory.bytes", @frontends %>
- memcached_multi_memory.bytes.label Current Bytes Used
- memcached_multi_bytes.graph_title Network Traffic
- memcached_multi_bytes.graph_args --base 1000
- memcached_multi_bytes.graph_vlabel bits in (-) / out (+)
- memcached_multi_bytes.graph_category memcached
- memcached_multi_bytes.graph_order bytes_read bytes_written
- memcached_multi_bytes.bytes_read.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_bytes.bytes_read", @frontends %>
- memcached_multi_bytes.bytes_read.label Network Traffic coming in (-)
- memcached_multi_bytes.bytes_read.cdef bytes_read,8,*
- memcached_multi_bytes.bytes_read.graph no
- memcached_multi_bytes.bytes_written.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_bytes.bytes_written", @frontends %>
- memcached_multi_bytes.bytes_written.negative bytes_read
- memcached_multi_bytes.bytes_written.label Traffic in (-) / out (+)
- memcached_multi_bytes.bytes_written.cdef bytes_written,8,*
-<% end -%>
-<% unless @tilecaches.empty? -%>
-
-# Configure compound graphs for tile.openstreetmap.org
-[tile.openstreetmap.org]
- update no
- network_in.graph_title Inbound network traffic
- network_in.graph_vlabel bits in per ${graph_period}
- network_in.graph_category network
- network_in.graph_order <%= Chef::Munin.expand "%%%name%%%=%%name%%.openstreetmap.org:if_%%interface%%.down", @tilecaches %>
- network_in.graph_total total
- network_in.graph_args --lower-limit 0
-<% @tilecaches.each do |tc| -%>
- network_in.<%= tc[:name].tr("-", "_") %>.label <%= tc[:name] %>
- network_in.<%= tc[:name].tr("-", "_") %>.cdef <%= tc[:name].tr("-", "_") %>,8,*
- network_in.<%= tc[:name].tr("-", "_") %>.draw AREASTACK
- network_in.<%= tc[:name].tr("-", "_") %>.min 0
-<% end -%>
- network_out.graph_title Outbound network traffic
- network_out.graph_vlabel bits out per ${graph_period}
- network_out.graph_category network
- network_out.graph_order <%= Chef::Munin.expand "%%%name%%%=%%name%%.openstreetmap.org:if_%%interface%%.up", @tilecaches %>
- network_out.graph_total total
- network_out.graph_args --lower-limit 0
-<% @tilecaches.each do |tc| -%>
- network_out.<%= tc[:name].tr("-", "_") %>.label <%= tc[:name] %>
- network_out.<%= tc[:name].tr("-", "_") %>.cdef <%= tc[:name].tr("-", "_") %>,8,*
- network_out.<%= tc[:name].tr("-", "_") %>.draw AREASTACK
- network_out.<%= tc[:name].tr("-", "_") %>.min 0
-<% end -%>
- squid_delay_pools.graph_title IPs being delayed with referer
- squid_delay_pools.graph_args --base 1000 -l 0
- squid_delay_pools.graph_vlabel IPs
- squid_delay_pools.graph_order squid_delay1
- squid_delay_pools.graph_category squid
- squid_delay_pools.squid_delay1.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:squid_delay_pools.squid_delay1", @tilecaches %>
- squid_delay_pools.squid_delay1.label IPs
- squid_delay_pools.squid_delay1.min 0
- squid_delay_pools.squid_delay1.draw AREA
- squid_delay_pools_noreferer.graph_title No-referer IPs being delayed
- squid_delay_pools_noreferer.graph_args --base 1000 -l 0
- squid_delay_pools_noreferer.graph_vlabel IPs
- squid_delay_pools_noreferer.graph_order squid_delay2
- squid_delay_pools_noreferer.graph_category squid
- squid_delay_pools_noreferer.squid_delay2.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:squid_delay_pools_noreferer.squid_delay2", @tilecaches %>
- squid_delay_pools_noreferer.squid_delay2.label IPs
- squid_delay_pools_noreferer.squid_delay2.min 0
- squid_delay_pools_noreferer.squid_delay2.draw AREA
- squid_requests.graph_title Squid client requests
- squid_requests.graph_args --base 1000 -l 0
- squid_requests.graph_vlabel requests / ${graph_period}
- squid_requests.graph_order <%= Chef::Munin.expand "%%%name%%%_hits=%%name%%.openstreetmap.org:squid_requests.hits %%%name%%%_errors=%%name%%.openstreetmap.org:squid_requests.errors %%%name%%%_requests=%%name%%.openstreetmap.org:squid_requests.requests", @tilecaches %> hits=<%= @tilecaches.first[:name] %>.openstreetmap.org:squid_requests.hits errors=<%= @tilecaches.first[:name] %>.openstreetmap.org:squid_requests.errors requests=<%= @tilecaches.first[:name] %>.openstreetmap.org:squid_requests.requests
- squid_requests.graph_total total
- squid_requests.graph_category squid
-<% @tilecaches.each do |tc| -%>
- squid_requests.<%= tc[:name].tr("-", "_") %>_hits.graph no
- squid_requests.<%= tc[:name].tr("-", "_") %>_errors.graph no
- squid_requests.<%= tc[:name].tr("-", "_") %>_requests.graph no
-<% end -%>
- squid_requests.hits.cdef 0,<%= Chef::Munin.expand "%%%name%%%_hits", @tilecaches, ",+," %>,+
- squid_requests.hits.label hits
- squid_requests.hits.draw AREA
- squid_requests.errors.cdef 0,<%= Chef::Munin.expand "%%%name%%%_errors", @tilecaches, ",+," %>,+
- squid_requests.errors.label errors
- squid_requests.errors.draw STACK
- squid_requests.requests.cdef 0,<%= Chef::Munin.expand "%%%name%%%_requests", @tilecaches, ",+," %>,+,hits,-,errors,-
- squid_requests.requests.label misses
- squid_requests.requests.draw STACK
- squid_traffic.graph_title Squid traffic status
- squid_traffic.graph_args --base 1000
- squid_traffic.graph_vlabel bits per ${graph_period}
- squid_traffic.graph_order kbytes_in kbytes_out hit_kbytes_out
- squid_traffic.graph_category squid
- squid_traffic.kbytes_in.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:squid_traffic.kbytes_in", @tilecaches %>
- squid_traffic.kbytes_in.label received
- squid_traffic.kbytes_in.cdef kbytes_in,8096,*
- squid_traffic.kbytes_out.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:squid_traffic.kbytes_out", @tilecaches %>
- squid_traffic.kbytes_out.label sent
- squid_traffic.kbytes_out.cdef kbytes_out,8096,*
- squid_traffic.hit_kbytes_out.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:squid_traffic.hit_kbytes_out", @tilecaches %>
- squid_traffic.hit_kbytes_out.label from cache
- squid_traffic.hit_kbytes_out.cdef hit_kbytes_out,8096,*
- squid_times_http.graph_title Squid Http Service Times
- squid_times_http.graph_category squid
- squid_times_http.graph_args --lower-limit 0
- squid_times_http.graph_vlabel median reponse times (s)
- squid_times_http.graph_order <%= Chef::Munin.expand "%%%name%%%=%%name%%.openstreetmap.org:squid_times.mean_http", @tilecaches %>
-<% @tilecaches.each do |tc| -%>
- squid_times_http.<%= tc[:name].tr("-", "_") %>.label <%= tc[:name] %>
-<% end -%>
- squid_times_cmis.graph_title Squid Cache Miss Service Times
- squid_times_cmis.graph_category squid
- squid_times_cmis.graph_args --lower-limit 0
- squid_times_cmis.graph_vlabel median reponse times (s)
- squid_times_cmis.graph_order <%= Chef::Munin.expand "%%%name%%%=%%name%%.openstreetmap.org:squid_times.mean_cmis", @tilecaches %>
-<% @tilecaches.each do |tc| -%>
- squid_times_cmis.<%= tc[:name].tr("-", "_") %>.label <%= tc[:name] %>
-<% end -%>
- squid_times_chits.graph_title Squid Cache Hit Service Times
- squid_times_chits.graph_category squid
- squid_times_chits.graph_args --lower-limit 0
- squid_times_chits.graph_vlabel median reponse times (s)
- squid_times_chits.graph_order <%= Chef::Munin.expand "%%%name%%%=%%name%%.openstreetmap.org:squid_times.mean_chits", @tilecaches %>
-<% @tilecaches.each do |tc| -%>
- squid_times_chits.<%= tc[:name].tr("-", "_") %>.label <%= tc[:name] %>
-<% end -%>
- squid_times_nhits.graph_title Squid Cache Near Hit Service Times
- squid_times_nhits.graph_category squid
- squid_times_nhits.graph_args --lower-limit 0
- squid_times_nhits.graph_vlabel median reponse times (s)
- squid_times_nhits.graph_order <%= Chef::Munin.expand "%%%name%%%=%%name%%.openstreetmap.org:squid_times.mean_nhits", @tilecaches %>
-<% @tilecaches.each do |tc| -%>
- squid_times_nhits.<%= tc[:name].tr("-", "_") %>.label <%= tc[:name] %>
-<% end -%>
- squid_times_nmr.graph_title Squid Cache Not Modified Service Times
- squid_times_nmr.graph_category squid
- squid_times_nmr.graph_args --lower-limit 0
- squid_times_nmr.graph_vlabel median reponse times (s)
- squid_times_nmr.graph_order <%= Chef::Munin.expand "%%%name%%%=%%name%%.openstreetmap.org:squid_times.mean_nmr", @tilecaches %>
-<% @tilecaches.each do |tc| -%>
- squid_times_nmr.<%= tc[:name].tr("-", "_") %>.label <%= tc[:name] %>
-<% end -%>
- squid_times_dnsl.graph_title Squid Cache DNS Lookup Service Times
- squid_times_dnsl.graph_category squid
- squid_times_dnsl.graph_args --lower-limit 0
- squid_times_dnsl.graph_vlabel median reponse times (s)
- squid_times_dnsl.graph_order <%= Chef::Munin.expand "%%%name%%%=%%name%%.openstreetmap.org:squid_times.mean_dnsl", @tilecaches %>
-<% @tilecaches.each do |tc| -%>
- squid_times_dnsl.<%= tc[:name].tr("-", "_") %>.label <%= tc[:name] %>
-<% end -%>
- squid_request_hitrates.graph_title Squid Cache Request Hit Rates
- squid_request_hitrates.graph_category squid
- squid_request_hitrates.graph_args --lower-limit 0 --upper-limit 100
- squid_request_hitrates.graph_vlabel %
- squid_request_hitrates.graph_order <%= Chef::Munin.expand "%%%name%%%_total=%%name%%.openstreetmap.org:squid_requests.requests %%%name%%%_hits=%%name%%.openstreetmap.org:squid_requests.hits", @tilecaches %>
-<% @tilecaches.each do |tc| -%>
- squid_request_hitrates.<%= tc[:name].tr("-", "_") %>_total.graph no
- squid_request_hitrates.<%= tc[:name].tr("-", "_") %>_hits.cdef <%= tc[:name].tr("-", "_") %>_hits,<%= tc[:name].tr("-", "_") %>_total,/,100,*
- squid_request_hitrates.<%= tc[:name].tr("-", "_") %>_hits.label <%= tc[:name] %>
- squid_request_hitrates.<%= tc[:name].tr("-", "_") %>_hits.draw LINE1
-<% end -%>
- squid_byte_hitrates.graph_title Squid Cache Byte Hit Rates
- squid_byte_hitrates.graph_category squid
- squid_byte_hitrates.graph_args --lower-limit 0 --upper-limit 100
- squid_byte_hitrates.graph_vlabel %
- squid_byte_hitrates.graph_order <%= Chef::Munin.expand "%%%name%%%_total=%%name%%.openstreetmap.org:squid_traffic.kbytes_out %%%name%%%_hits=%%name%%.openstreetmap.org:squid_traffic.hit_kbytes_out", @tilecaches %>
-<% @tilecaches.each do |tc| -%>
- squid_byte_hitrates.<%= tc[:name].tr("-", "_") %>_total.graph no
- squid_byte_hitrates.<%= tc[:name].tr("-", "_") %>_hits.cdef <%= tc[:name].tr("-", "_") %>_hits,<%= tc[:name].tr("-", "_") %>_total,/,100,*
- squid_byte_hitrates.<%= tc[:name].tr("-", "_") %>_hits.label <%= tc[:name] %>
- squid_byte_hitrates.<%= tc[:name].tr("-", "_") %>_hits.draw LINE1
-<% end -%>
- nginx_requests.graph_title Nginx requests
- nginx_requests.graph_vlabel Requests per ${graph_period}
- nginx_requests.graph_category nginx
- nginx_requests.graph_order <%= Chef::Munin.expand "%%%name%%%=%%name%%.openstreetmap.org:nginx_request.request", @tilecaches %>
- nginx_requests.graph_total total
- nginx_requests.graph_args --lower-limit 0
-<% @tilecaches.each do |tc| -%>
- nginx_requests.<%= tc[:name].tr("-", "_") %>.label <%= tc[:name] %>
- nginx_requests.<%= tc[:name].tr("-", "_") %>.draw AREASTACK
- nginx_requests.<%= tc[:name].tr("-", "_") %>.min 0
-<% end -%>
-<% end -%>
-<% unless @renderers.empty? -%>
-
-# Configure compound graphs for render.openstreetmap.org
-[render.openstreetmap.org]
- update no
- apache_accesses.graph_title Apache accesses
- apache_accesses.graph_vlabel accesses / ${graph_period}
- apache_accesses.graph_category apache
- apache_accesses.graph_order <%= Chef::Munin.expand "%%%name%%%=%%name%%.openstreetmap.org:apache_accesses.accesses80", @renderers %>
- apache_accesses.graph_total total
- apache_accesses.graph_args --lower-limit 0
-<% @renderers.each do |rs| -%>
- apache_accesses.<%= rs[:name].tr("-", "_") %>.label <%= rs[:name] %>
- apache_accesses.<%= rs[:name].tr("-", "_") %>.draw AREASTACK
- apache_accesses.<%= rs[:name].tr("-", "_") %>.min 0
-<% end -%>
- apache_volume.graph_title Apache volume
- apache_volume.graph_vlabel bytes per ${graph_period}
- apache_volume.graph_category apache
- apache_volume.graph_order <%= Chef::Munin.expand "%%%name%%%=%%name%%.openstreetmap.org:apache_volume.volume80", @renderers %>
- apache_volume.graph_total total
- apache_volume.graph_args --lower-limit 0
-<% @renderers.each do |rs| -%>
- apache_volume.<%= rs[:name].tr("-", "_") %>.label <%= rs[:name] %>
- apache_volume.<%= rs[:name].tr("-", "_") %>.draw AREASTACK
- apache_volume.<%= rs[:name].tr("-", "_") %>.min 0
-<% end -%>
- network_in.graph_title Inbound network traffic
- network_in.graph_vlabel bits in per ${graph_period}
- network_in.graph_category network
- network_in.graph_order <%= Chef::Munin.expand "%%%name%%%=%%name%%.openstreetmap.org:if_%%interface%%.down", @renderers %>
- network_in.graph_total total
- network_in.graph_args --lower-limit 0
-<% @renderers.each do |rs| -%>
- network_in.<%= rs[:name].tr("-", "_") %>.label <%= rs[:name] %>
- network_in.<%= rs[:name].tr("-", "_") %>.cdef <%= rs[:name].tr("-", "_") %>,8,*
- network_in.<%= rs[:name].tr("-", "_") %>.draw AREASTACK
- network_in.<%= rs[:name].tr("-", "_") %>.min 0
-<% end -%>
- network_out.graph_title Outbound network traffic
- network_out.graph_vlabel bits out per ${graph_period}
- network_out.graph_category network
- network_out.graph_order <%= Chef::Munin.expand "%%%name%%%=%%name%%.openstreetmap.org:if_%%interface%%.up", @renderers %>
- network_out.graph_total total
- network_out.graph_args --lower-limit 0
-<% @renderers.each do |rs| -%>
- network_out.<%= rs[:name].tr("-", "_") %>.label <%= rs[:name] %>
- network_out.<%= rs[:name].tr("-", "_") %>.cdef <%= rs[:name].tr("-", "_") %>,8,*
- network_out.<%= rs[:name].tr("-", "_") %>.draw AREASTACK
- network_out.<%= rs[:name].tr("-", "_") %>.min 0
-<% end -%>
- mod_tile_fresh.graph_title freshness of served tiles
- mod_tile_fresh.graph_args --base 1000 -l 0
- mod_tile_fresh.graph_vlabel tiles per ${graph_period}
- mod_tile_fresh.graph_order fresh freshrender old oldrender outdated outdatedrender
- mod_tile_fresh.graph_category mod_tile
- mod_tile_fresh.fresh.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:mod_tile_fresh.fresh", @renderers %>
- mod_tile_fresh.fresh.label Fresh from disk
- mod_tile_fresh.fresh.draw AREA
- mod_tile_fresh.freshrender.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:mod_tile_fresh.freshrender", @renderers %>
- mod_tile_fresh.freshrender.label Freshly rendered
- mod_tile_fresh.freshrender.draw STACK
- mod_tile_fresh.old.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:mod_tile_fresh.old", @renderers %>
- mod_tile_fresh.old.label Old from disk
- mod_tile_fresh.old.draw STACK
- mod_tile_fresh.oldrender.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:mod_tile_fresh.oldrender", @renderers %>
- mod_tile_fresh.oldrender.label Old tile, attempted render
- mod_tile_fresh.oldrender.draw STACK
- mod_tile_fresh.outdated.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:mod_tile_fresh.outdated", @renderers %>
- mod_tile_fresh.outdated.label Outdated from disk
- mod_tile_fresh.outdated.draw STACK
- mod_tile_fresh.outdatedrender.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:mod_tile_fresh.outdatedrender", @renderers %>
- mod_tile_fresh.outdatedrender.label Outdated tile, attempted render
- mod_tile_fresh.outdatedrender.draw STACK
- mod_tile_response.graph_title mod_tile HTTP response codes
- mod_tile_response.graph_args --base 1000 -l 0
- mod_tile_response.graph_vlabel responses per ${graph_period}
- mod_tile_response.graph_order response200 response304 response404 response500
- mod_tile_response.graph_category mod_tile
- mod_tile_response.response200.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:mod_tile_response.response200", @renderers %>
- mod_tile_response.response200.label 200 OK
- mod_tile_response.response200.draw AREA
- mod_tile_response.response304.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:mod_tile_response.response304", @renderers %>
- mod_tile_response.response304.label 304 Not Modified
- mod_tile_response.response304.draw STACK
- mod_tile_response.response404.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:mod_tile_response.response404", @renderers %>
- mod_tile_response.response404.label 404 Not Found
- mod_tile_response.response404.draw STACK
- mod_tile_response.response500.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:mod_tile_response.response500", @renderers %>
- mod_tile_response.response500.label 500 Internal Error
- mod_tile_response.response500.draw STACK
- mod_tile_zoom.graph_title mod_tile responses by zoom layer
- mod_tile_zoom.graph_args --base 1000 -l 0
- mod_tile_zoom.graph_vlabel responses per ${graph_period}
- mod_tile_zoom.graph_order z1 z2 z3 z4 z5 z6
- mod_tile_zoom.graph_category mod_tile
- mod_tile_zoom.z1.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:mod_tile_zoom.z1", @renderers %>
- mod_tile_zoom.z1.label z1-8
- mod_tile_zoom.z1.draw AREA
- mod_tile_zoom.z2.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:mod_tile_zoom.z2", @renderers %>
- mod_tile_zoom.z2.label z9-12
- mod_tile_zoom.z2.draw STACK
- mod_tile_zoom.z3.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:mod_tile_zoom.z3", @renderers %>
- mod_tile_zoom.z3.label z13-14
- mod_tile_zoom.z3.draw STACK
- mod_tile_zoom.z4.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:mod_tile_zoom.z4", @renderers %>
- mod_tile_zoom.z4.label z15-16
- mod_tile_zoom.z4.draw STACK
- mod_tile_zoom.z5.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:mod_tile_zoom.z5", @renderers %>
- mod_tile_zoom.z5.label z17-18
- mod_tile_zoom.z5.draw STACK
- mod_tile_zoom.z6.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:mod_tile_zoom.z6", @renderers %>
- mod_tile_zoom.z6.label z19-20
- mod_tile_zoom.z6.draw STACK
- renderd_queue.graph_title Renderd queue length
- renderd_queue.graph_args --base 1000 -l 0
- renderd_queue.graph_vlabel metatiles
- renderd_queue.graph_order reqPrio req reqLow dirty reqBulk
- renderd_queue.graph_category renderd
- renderd_queue.reqPrio.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_queue.reqPrio", @renderers %>
- renderd_queue.reqPrio.label Priority request Queue
- renderd_queue.reqPrio.type GAUGE
- renderd_queue.req.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_queue.req", @renderers %>
- renderd_queue.req.label Request Queue
- renderd_queue.req.type GAUGE
- renderd_queue.reqLow.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_queue.reqLow", @renderers %>
- renderd_queue.reqLow.label Low priority request Queue
- renderd_queue.reqLow.type GAUGE
- renderd_queue.dirty.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_queue.dirty", @renderers %>
- renderd_queue.dirty.label Dirty Queue
- renderd_queue.dirty.type GAUGE
- renderd_queue.reqBulk.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_queue.reqBulk", @renderers %>
- renderd_queue.reqBulk.label Bulk request Queue
- renderd_queue.reqBulk.type GAUGE
- renderd_processed.graph_title Renderd throughput
- renderd_processed.graph_args --base 1000 -l 0
- renderd_processed.graph_vlabel Metatiles per ${graph_period}
- renderd_processed.graph_order reqPrio req reqLow dirty reqBulk dropped
- renderd_processed.graph_category renderd
- renderd_processed.graph_info Displays the number of metatiles being rendered by renderd per ${graph_period}
- renderd_processed.reqPrio.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_processed.reqPrio", @renderers %>
- renderd_processed.reqPrio.label Priority request Queue
- renderd_processed.reqPrio.draw AREA
- renderd_processed.reqPrio.info Throughput of Metatiles submitted high priority for on the fly rendering
- renderd_processed.req.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_processed.req", @renderers %>
- renderd_processed.req.label Request Queue
- renderd_processed.req.draw STACK
- renderd_processed.req.info Throughput of Metatiles submitted for on the fly rendering
- renderd_processed.reqLow.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_processed.reqLow", @renderers %>
- renderd_processed.reqLow.label Low priority request Queue
- renderd_processed.reqLow.draw STACK
- renderd_processed.reqLow.info Throughput of Metatiles submitted low priority for on the fly rendering
- renderd_processed.dirty.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_processed.dirty", @renderers %>
- renderd_processed.dirty.label Dirty Queue
- renderd_processed.dirty.draw STACK
- renderd_processed.dirty.info Throughput of dirty Metatiles submitted for re-render
- renderd_processed.reqBulk.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_processed.reqBulk", @renderers %>
- renderd_processed.reqBulk.label Bulk request Queue
- renderd_processed.reqBulk.draw STACK
- renderd_processed.reqBulk.info Throughput of Metatiles submitted with background priority
- renderd_processed.dropped.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_processed.dropped", @renderers %>
- renderd_processed.dropped.label Dropped (x20)
- renderd_processed.dropped.draw LINE2
- renderd_processed.dropped.info Number of Tiles dropped due to queue overload (x20)
- renderd_processed.dropped.cdef dropped,20,/
- renderd_zoom.graph_title Renderd throughput by zoom
- renderd_zoom.graph_args --base 1000 -l 0
- renderd_zoom.graph_vlabel Metatiles per ${graph_period}
- renderd_zoom.graph_order z1 z2 z3 z4 z5 z6
- renderd_zoom.graph_category renderd
- renderd_zoom.graph_info Displays the number of metatiles being rendered by renderd per ${graph_period}
- renderd_zoom.z1.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_zoom.z1", @renderers %>
- renderd_zoom.z1.label zoom z0 - z8
- renderd_zoom.z1.draw AREA
- renderd_zoom.z1.info Throughput of Metatiles for z0 - z8
- renderd_zoom.z2.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_zoom.z2", @renderers %>
- renderd_zoom.z2.label zoom z9 - z12
- renderd_zoom.z2.draw STACK
- renderd_zoom.z2.info Throughput of Metatiles for z9 - z12
- renderd_zoom.z3.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_zoom.z3", @renderers %>
- renderd_zoom.z3.label zoom z13 - z14
- renderd_zoom.z3.draw STACK
- renderd_zoom.z3.info Throughput of Metatiles for z13 - z14
- renderd_zoom.z4.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_zoom.z4", @renderers %>
- renderd_zoom.z4.label zoom z15 - z16
- renderd_zoom.z4.draw STACK
- renderd_zoom.z4.info Throughput of Metatiles for z15 - z16
- renderd_zoom.z5.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_zoom.z5", @renderers %>
- renderd_zoom.z5.label zoom z17 - z18
- renderd_zoom.z5.draw STACK
- renderd_zoom.z5.info Throughput of Metatiles for z17 - z18
- renderd_zoom.z6.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_zoom.z6", @renderers %>
- renderd_zoom.z6.label zoom z19 - z20
- renderd_zoom.z6.draw STACK
- renderd_zoom.z6.info Throughput of Metatiles for z19 - z20
- renderd_queue_time.graph_title Renderd time spent by queue
- renderd_queue_time.graph_args --base 1000 -l 0
- renderd_queue_time.graph_vlabel metatiles
- renderd_queue_time.graph_order reqPrio req reqLow dirty reqBulk
- renderd_queue_time.graph_category renderd
- renderd_queue_time.reqPrio.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_queue_time.reqPrio", @renderers %>
- renderd_queue_time.reqPrio.label Priority request queue
- renderd_queue_time.reqPrio.cdef reqPrio,1000,/
- renderd_queue_time.reqPrio.draw AREA
- renderd_queue_time.reqPrio.info Time for priority request queue
- renderd_queue_time.req.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_queue_time.req", @renderers %>
- renderd_queue_time.req.label Request queue
- renderd_queue_time.req.cdef req,1000,/
- renderd_queue_time.req.draw STACK
- renderd_queue_time.req.info Time for Request queue
- renderd_queue_time.reqLow.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_queue_time.reqLow", @renderers %>
- renderd_queue_time.reqLow.label Low priority request queue
- renderd_queue_time.reqLow.cdef reqLow,1000,/
- renderd_queue_time.reqLow.draw STACK
- renderd_queue_time.reqLow.info Time for low priority request queue
- renderd_queue_time.dirty.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_queue_time.dirty", @renderers %>
- renderd_queue_time.dirty.label Dirty queue
- renderd_queue_time.dirty.cdef dirty,1000,/
- renderd_queue_time.dirty.draw STACK
- renderd_queue_time.dirty.info Time for dirty queue
- renderd_queue_time.reqBulk.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_queue_time.reqBulk", @renderers %>
- renderd_queue_time.reqBulk.label Bulk queue
- renderd_queue_time.reqBulk.cdef reqBulk,1000,/
- renderd_queue_time.reqBulk.draw STACK
- renderd_queue_time.reqBulk.info Time for bulk queue
- renderd_zoom_time.graph_title Renderd time spent by zoom
- renderd_zoom_time.graph_args --base 1000 -l 0
- renderd_zoom_time.graph_vlabel time spent per ${graph_period}
- renderd_zoom_time.graph_order zoomtime1 zoomtime2 zoomtime3 zoomtime4 zoomtime5 zoomtime6
- renderd_zoom_time.graph_category renderd
- renderd_zoom_time.graph_info Displays the amount of time renderd has spent rendering tiles of a given zoom per ${graph_period}
- renderd_zoom_time.zoomtime1.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_zoom_time.zoomtime1", @renderers %>
- renderd_zoom_time.zoomtime1.label zoom z0 - z8
- renderd_zoom_time.zoomtime1.cdef zoomtime1,1000,/
- renderd_zoom_time.zoomtime1.draw AREA
- renderd_zoom_time.zoomtime1.info Time for Metatiles z0 - z8
- renderd_zoom_time.zoomtime2.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_zoom_time.zoomtime2", @renderers %>
- renderd_zoom_time.zoomtime2.label zoom z9 - z12
- renderd_zoom_time.zoomtime2.cdef zoomtime2,1000,/
- renderd_zoom_time.zoomtime2.draw STACK
- renderd_zoom_time.zoomtime2.info Time for Metatiles for z9 - z12
- renderd_zoom_time.zoomtime3.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_zoom_time.zoomtime3", @renderers %>
- renderd_zoom_time.zoomtime3.label zoom z13 - z14
- renderd_zoom_time.zoomtime3.cdef zoomtime3,1000,/
- renderd_zoom_time.zoomtime3.draw STACK
- renderd_zoom_time.zoomtime3.info Time for Metatiles for z13 - z14
- renderd_zoom_time.zoomtime4.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_zoom_time.zoomtime4", @renderers %>
- renderd_zoom_time.zoomtime4.label zoom z15 - z16
- renderd_zoom_time.zoomtime4.cdef zoomtime4,1000,/
- renderd_zoom_time.zoomtime4.draw STACK
- renderd_zoom_time.zoomtime4.info Time for Metatiles for z15 - z16
- renderd_zoom_time.zoomtime5.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_zoom_time.zoomtime5", @renderers %>
- renderd_zoom_time.zoomtime5.label zoom z17 - z18
- renderd_zoom_time.zoomtime5.cdef zoomtime5,1000,/
- renderd_zoom_time.zoomtime5.draw STACK
- renderd_zoom_time.zoomtime5.info Time for Metatiles for z17 - z18
- renderd_zoom_time.zoomtime6.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:renderd_zoom_time.zoomtime6", @renderers %>
- renderd_zoom_time.zoomtime6.label zoom z19 - z20
- renderd_zoom_time.zoomtime6.cdef zoomtime6,1000,/
- renderd_zoom_time.zoomtime6.draw STACK
- renderd_zoom_time.zoomtime6.info Time for Metatiles for z19 - z20
-<% end -%>
-<% unless @geocoders.empty? -%>
-
-# Configure compound graphs for nominatim.openstreetmap.org
-[nominatim.openstreetmap.org]
- update no
- nominatim_requests.graph_title Requests by API call
- nominatim_requests.graph_args --base 1000 -l 0
- nominatim_requests.graph_vlabel requests per minute
- nominatim_requests.graph_category nominatim
- nominatim_requests.graph_order z1 z2 z3 z4
- nominatim_requests.z1.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:nominatim_requests.z1", @geocoders %>
- nominatim_requests.z1.label reverse
- nominatim_requests.z1.draw AREA
- nominatim_requests.z1.type GAUGE
- nominatim_requests.z2.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:nominatim_requests.z2", @geocoders %>
- nominatim_requests.z2.label search (successful)
- nominatim_requests.z2.draw STACK
- nominatim_requests.z2.type GAUGE
- nominatim_requests.z3.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:nominatim_requests.z3", @geocoders %>
- nominatim_requests.z3.label search (no result)
- nominatim_requests.z3.draw STACK
- nominatim_requests.z3.type GAUGE
- nominatim_requests.z4.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:nominatim_requests.z4", @geocoders %>
- nominatim_requests.z4.label details
- nominatim_requests.z4.draw STACK
- nominatim_requests.z4.type GAUGE
- nominatim_throttled_ips.graph_title Restricted IPs
- nominatim_throttled_ips.graph_args -l 0
- nominatim_throttled_ips.graph_vlabel number of IPs
- nominatim_throttled_ips.graph_category nominatim
- nominatim_throttled_ips.graph_order bulk block
- nominatim_throttled_ips.bulk.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:nominatim_throttled_ips.bulk", @geocoders %>
- nominatim_throttled_ips.bulk.label bulk
- nominatim_throttled_ips.bulk.draw AREA
- nominatim_throttled_ips.bulk.type GAUGE
- nominatim_throttled_ips.block.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:nominatim_throttled_ips.block", @geocoders %>
- nominatim_throttled_ips.block.label blocked
- nominatim_throttled_ips.block.draw STACK
- nominatim_throttled_ips.block.type GAUGE
-<% end -%>
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-# Full path to daemon
-DAEMON=/usr/bin/rrdcached
-
-# Optional override flush interval, in seconds.
-WRITE_TIMEOUT=1800
-
-# Optional override maximum write delay, in seconds.
-WRITE_JITTER=1800
-
-# Optional override number of write_threads
-#WRITE_THREADS=4
-
-# Where database files are placed. If left unset, the default /tmp will
-# be used. NB: The daemon will reject a directory that has symlinks as
-# components. NB: You may want to have -B in BASE_OPTS.
-BASE_PATH=/var/lib/munin/
-
-# Where journal files are placed. If left unset, journaling will
-# be disabled.
-JOURNAL_PATH=/var/lib/munin/rrdcached/
-
-# FHS standard placement for process ID file.
-PIDFILE=/var/run/rrdcached.pid
-
-# FHS standard placement for local control socket.
-SOCKFILE=/var/run/rrdcached.sock
-
-# Optional override group that should own/access the local control
-# socket
-SOCKGROUP=munin
-
-# Optional override access mode of local control socket.
-SOCKMODE=0666
-
-# Optional unprivileged group to run under when daemon. If unset
-# retains invocation group privileges.
-#DAEMON_GROUP=_rrdcached
-
-# Optional unprivileged user to run under when daemon. If unset
-# retains invocation user privileges.
-#DAEMON_USER=_rrdcached
-
-# Network socket address requests. Use in conjunction with SOCKFILE to
-# also listen on INET domain sockets. The option is a lower-case ell
-# ASCII 108 = 0x6c, and should be repeated for each address. The
-# parameter is an optional IP address, followed by an optional port with
-# a colon separating it from the address. The empty string is
-# interpreted as "open sockets on the default port on all available
-# interfaces", but generally does not pass through init script functions
-# so use -L with no parameters for that configuration.
-#NETWORK_OPTIONS="-L"
-
-# Any other options not specifically supported by the script (-P, -f,
-# -F, -B).
-BASE_OPTIONS="-F -B"
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-[sensors_volt]
-env.volt_warn_percent 0
version "1.0.0"
supports "ubuntu"
depends "chef"
-depends "munin"
depends "prometheus"
# limitations under the License.
#
-include_recipe "munin"
include_recipe "prometheus"
-package "mysql-server"
-package "mysql-client"
+mysql_variant = if platform?("ubuntu")
+ "mysql"
+ else
+ "mariadb"
+ end
-service "mysql" do
+package "#{mysql_variant}-server"
+package "#{mysql_variant}-client"
+
+service "#{mysql_variant}" do
action [:enable, :start]
supports :status => true, :restart => true
end
-template "/etc/mysql/mysql.conf.d/zzz-chef.cnf" do
+template "/etc/mysql/#{mysql_variant}.conf.d/zzz-chef.cnf" do
source "my.cnf.erb"
owner "root"
group "root"
mode "644"
- notifies :restart, "service[mysql]"
+ notifies :restart, "service[#{mysql_variant}]"
end
-package "libdbd-mysql-perl"
-package "libcache-cache-perl"
-
-%w[
- commands connections files handler_read handler_tmp handler_transaction
- handler_write innodb_bpool innodb_bpool_act innodb_history_list_length
- innodb_insert_buf innodb_io innodb_io_pend innodb_log innodb_queries
- innodb_read_views innodb_rows innodb_semaphores innodb_srv_master_thread
- innodb_tnx max_mem mrr myisam_indexes network_traffic performance
- qcache qcache_mem select_types slow sorts table_definitions table_locks
- tmp_tables
-].each do |stat|
- munin_plugin "mysql_#{stat}" do
- target "mysql_"
- end
+service "apparmor" do
+ action :nothing
end
-%w[
- bin_relay_log files_tables replication
-].each do |stat|
- munin_plugin "mysql_#{stat}" do
- action :delete
- end
+template "/etc/apparmor.d/local/usr.sbin.mysqld" do
+ source "apparmor.erb"
+ owner "root"
+ group "root"
+ mode "644"
+ notifies :restart, "service[apparmor]"
+ only_if { ::Dir.exist?("/sys/kernel/security/apparmor") }
end
mysql_password = persistent_token("mysql", "prometheus", "password")
prometheus_exporter "mysqld" do
port 9104
- environment "DATA_SOURCE_NAME" => "prometheus:#{mysql_password}@(localhost:3306)/"
+ options "--mysqld.username=prometheus"
+ environment "MYSQLD_EXPORTER_PASSWORD" => mysql_password
end
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+<% if node[:mysql][:settings][:mysqld]&.dig(:secure_file_priv) -%>
+<%= node[:mysql][:settings][:mysqld][:secure_file_priv] %>/* rw,
+<% end -%>
default[:networking][:firewall][:enabled] = true
-default[:networking][:firewall][:inet] = []
-default[:networking][:firewall][:inet6] = []
-default[:networking][:firewall][:http_rate_limit] = "-"
-default[:networking][:firewall][:http_connection_limit] = "-"
-default[:networking][:firewall][:log] = true
-default[:networking][:firewall][:mark] = true
-default[:networking][:firewall][:raw] = true
-default[:networking][:firewall][:mangle] = true
+default[:networking][:firewall][:sets] = []
+default[:networking][:firewall][:helpers] = []
+default[:networking][:firewall][:incoming] = []
+default[:networking][:firewall][:outgoing] = []
+default[:networking][:firewall][:http_rate_limit] = nil
+default[:networking][:firewall][:http_connection_limit] = nil
+default[:networking][:firewall][:allowlist] = []
default[:networking][:roles] = {}
default[:networking][:interfaces] = {}
-default[:networking][:nameservers] = %w[1.1.1.1 1.0.0.1 2606:4700:4700::1111 2606:4700:4700::1001]
+default[:networking][:nameservers] = %w[8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844]
default[:networking][:search] = []
default[:networking][:dnssec] = "allow-downgrade"
default[:networking][:hostname] = node.name
default[:networking][:wireguard][:enabled] = true
-default[:networking][:wireguard][:keepalive] = false
+default[:networking][:wireguard][:keepalive] = 180
default[:networking][:wireguard][:peers] = []
-class Chef
- class Node
- def interfaces(options = {}, &block)
- interfaces = []
+module OpenStreetMap
+ module Mixin
+ module Interfaces
+ def interfaces(role: nil)
+ networking = construct_attributes[:networking] || {}
+ networking_interfaces = networking[:interfaces] || {}
- networking = construct_attributes[:networking] || {}
- networking_interfaces = networking[:interfaces] || {}
-
- networking_interfaces.each_value do |interface|
- next unless options[:role].nil? || interface[:role].to_s == options[:role].to_s
- next unless options[:family].nil? || interface[:family].to_s == options[:family].to_s
-
- if block.nil?
- interfaces << interface
- else
- yield interface
+ networking_interfaces.each_value.select do |interface|
+ role.nil? || interface[:role].to_s == role.to_s
end
end
-
- interfaces
end
end
end
+
+Chef::Node.include(OpenStreetMap::Mixin::Interfaces)
-class Chef
- class Node
- def ipaddresses(options = {}, &block)
- addresses = []
+require "ipaddr"
- interfaces(options).each do |interface|
- address = interface[:public_address] || interface[:address]
+module OpenStreetMap
+ module Mixin
+ module IPAddresses
+ class Address
+ attr_reader :address, :prefix, :gateway, :network, :netmask
- next if address.nil?
+ def initialize(address)
+ @address = address[:public_address] || address[:address]
+ @prefix = address[:prefix]
+ @gateway = address[:gateway]
- if block.nil?
- addresses << address
- else
- yield address
+ ip = IPAddr.new(address[:address]).mask(address[:prefix])
+
+ @network = ip.to_s
+ @netmask = ip.netmask
+ end
+
+ def <=>(other)
+ address <=> other.address
+ end
+
+ def to_s
+ address
+ end
+
+ def to_str
+ address
+ end
+
+ def subnet
+ "#{@network}/#{@prefix}"
end
end
- addresses
- end
+ def ipaddresses(role: nil, family: nil)
+ interfaces(:role => role).each_with_object([]) do |interface, addresses|
+ addresses << Address.new(interface[:inet]) if interface[:inet] && (family.nil? || family == :inet)
+ addresses << Address.new(interface[:inet6]) if interface[:inet6] && (family.nil? || family == :inet6)
+ end
+ end
- def internal_ipaddress(options = {})
- ipaddresses(options.merge(:role => :internal)).first
- end
+ def internal_ipaddress(family: nil)
+ ipaddresses(:role => :internal, :family => family).first
+ end
- def external_ipaddress(options = {})
- ipaddresses(options.merge(:role => :external)).first
+ def external_ipaddress(family: nil)
+ ipaddresses(:role => :external, :family => family).first
+ end
end
end
end
+
+Chef::Node.include(OpenStreetMap::Mixin::IPAddresses)
keys = data_bag_item("networking", "keys")
-package "netplan.io"
-
-netplan = {
- "network" => {
- "version" => 2,
- "renderer" => "networkd",
- "ethernets" => {},
- "bonds" => {},
- "vlans" => {}
- }
-}
-
-node[:networking][:interfaces].each do |name, interface|
- if interface[:interface]
- if interface[:role] && (role = node[:networking][:roles][interface[:role]])
- if role[interface[:family]]
- node.default[:networking][:interfaces][name][:prefix] = role[interface[:family]][:prefix]
- node.default[:networking][:interfaces][name][:gateway] = role[interface[:family]][:gateway]
- node.default[:networking][:interfaces][name][:routes] = role[interface[:family]][:routes]
- end
-
- node.default[:networking][:interfaces][name][:metric] = role[:metric]
- node.default[:networking][:interfaces][name][:zone] = role[:zone]
- end
+file "/etc/netplan/00-installer-config.yaml" do
+ action :delete
+end
- if interface[:address]
- prefix = node[:networking][:interfaces][name][:prefix]
+file "/etc/netplan/01-netcfg.yaml" do
+ action :delete
+end
- node.default[:networking][:interfaces][name][:netmask] = (~IPAddr.new(interface[:address]).mask(0)).mask(prefix)
- node.default[:networking][:interfaces][name][:network] = IPAddr.new(interface[:address]).mask(prefix)
- end
+file "/etc/netplan/50-cloud-init.yaml" do
+ action :delete
+end
- interface = node[:networking][:interfaces][name]
-
- deviceplan = if interface[:interface] =~ /^(.*)\.(\d+)$/
- netplan["network"]["vlans"][interface[:interface]] ||= {
- "id" => Regexp.last_match(2).to_i,
- "link" => Regexp.last_match(1),
- "accept-ra" => false,
- "addresses" => [],
- "routes" => []
- }
- elsif interface[:interface] =~ /^bond\d+$/
- netplan["network"]["bonds"][interface[:interface]] ||= {
- "accept-ra" => false,
- "addresses" => [],
- "routes" => []
- }
- else
- netplan["network"]["ethernets"][interface[:interface]] ||= {
- "accept-ra" => false,
- "addresses" => [],
- "routes" => []
- }
- end
-
- if interface[:address]
- deviceplan["addresses"].push("#{interface[:address]}/#{prefix}")
- end
+file "/etc/netplan/99-chef.yaml" do
+ action :delete
+end
- if interface[:mtu]
- deviceplan["mtu"] = interface[:mtu]
- end
+package "ifupdown" do
+ action :purge
+end
- if interface[:bond]
- deviceplan["interfaces"] = interface[:bond][:slaves].to_a
+package "netplan.io" do
+ action :purge
+end
- deviceplan["parameters"] = {
- "mode" => interface[:bond][:mode] || "active-backup",
- "primary" => interface[:bond][:slaves].first,
- "mii-monitor-interval" => interface[:bond][:miimon] || 100,
- "down-delay" => interface[:bond][:downdelay] || 200,
- "up-delay" => interface[:bond][:updelay] || 200
- }
+package "cloud-init" do
+ action :purge
+end
- deviceplan["parameters"]["transmit-hash-policy"] = interface[:bond][:xmithashpolicy] if interface[:bond][:xmithashpolicy]
- deviceplan["parameters"]["lacp-rate"] = interface[:bond][:lacprate] if interface[:bond][:lacprate]
- end
+interfaces = node[:networking][:interfaces].collect do |name, interface|
+ [interface[:interface], name]
+end.to_h
- if interface[:gateway]
- if interface[:family] == "inet"
- default_route = "0.0.0.0/0"
- elsif interface[:family] == "inet6"
- default_route = "::/0"
- end
+node[:networking][:interfaces].each do |name, interface|
+ if interface[:interface] =~ /^(.*)\.(\d+)$/
+ vlan_interface = Regexp.last_match(1)
+ vlan_id = Regexp.last_match(2)
- deviceplan["routes"].push(
- "to" => default_route,
- "via" => interface[:gateway],
- "metric" => interface[:metric],
- "on-link" => true
- )
-
- # This ordering relies on systemd-networkd adding routes
- # in reverse order and will need moving before the previous
- # route once that is fixed:
- #
- # https://github.com/systemd/systemd/issues/5430
- # https://github.com/systemd/systemd/pull/10938
- if interface[:family] == "inet6" &&
- !interface[:network].include?(interface[:gateway]) &&
- !IPAddr.new("fe80::/64").include?(interface[:gateway])
- deviceplan["routes"].push(
- "to" => interface[:gateway],
- "scope" => "link"
- )
- end
- end
+ parent = interfaces[vlan_interface] || "vlans_#{vlan_interface}"
- if interface[:routes]
- interface[:routes].each do |to, parameters|
- next if parameters[:via] == interface[:address]
+ node.default_unless[:networking][:interfaces][parent][:interface] = vlan_interface
+ node.default_unless[:networking][:interfaces][parent][:vlans] = []
- route = {
- "to" => to
- }
+ node.default[:networking][:interfaces][parent][:vlans] << vlan_id
+ end
- route["type"] = parameters[:type] if parameters[:type]
- route["via"] = parameters[:via] if parameters[:via]
- route["metric"] = parameters[:metric] if parameters[:metric]
+ next unless interface[:role] && (role = node[:networking][:roles][interface[:role]])
- deviceplan["routes"].push(route)
- end
- end
- else
- node.rm(:networking, :interfaces, name)
+ if interface[:inet] && role[:inet]
+ node.default_unless[:networking][:interfaces][name][:inet][:prefix] = role[:inet][:prefix]
+ node.default_unless[:networking][:interfaces][name][:inet][:gateway] = role[:inet][:gateway]
+ node.default_unless[:networking][:interfaces][name][:inet][:routes] = role[:inet][:routes]
end
-end
-netplan["network"]["bonds"].each_value do |bond|
- bond["interfaces"].each do |interface|
- netplan["network"]["ethernets"][interface] ||= { "accept-ra" => false }
+ if interface[:inet6] && role[:inet6]
+ node.default_unless[:networking][:interfaces][name][:inet6][:prefix] = role[:inet6][:prefix]
+ node.default_unless[:networking][:interfaces][name][:inet6][:gateway] = role[:inet6][:gateway]
+ node.default_unless[:networking][:interfaces][name][:inet6][:routes] = role[:inet6][:routes]
end
-end
-netplan["network"]["vlans"].each_value do |vlan|
- unless vlan["link"] =~ /^bond\d+$/
- netplan["network"]["ethernets"][vlan["link"]] ||= { "accept-ra" => false }
- end
+ node.default_unless[:networking][:interfaces][name][:metric] = role[:metric]
+ node.default_unless[:networking][:interfaces][name][:zone] = role[:zone]
end
-file "/etc/netplan/01-netcfg.yaml" do
- action :delete
-end
+node[:networking][:interfaces].each do |_, interface|
+ if interface[:interface] =~ /^.*\.(\d+)$/
+ template "/etc/systemd/network/10-#{interface[:interface]}.netdev" do
+ source "vlan.netdev.erb"
+ owner "root"
+ group "root"
+ mode "644"
+ variables :interface => interface, :vlan => Regexp.last_match(1)
+ notifies :run, "notify_group[networkctl-reload]"
+ end
+ elsif interface[:interface] =~ /^bond\d+$/
+ template "/etc/systemd/network/10-#{interface[:interface]}.netdev" do
+ source "bond.netdev.erb"
+ owner "root"
+ group "root"
+ mode "644"
+ variables :interface => interface
+ notifies :run, "notify_group[networkctl-reload]"
+ end
-file "/etc/netplan/50-cloud-init.yaml" do
- action :delete
+ interface[:bond][:slaves].each do |slave|
+ template "/etc/systemd/network/10-#{slave}.network" do
+ source "slave.network.erb"
+ owner "root"
+ group "root"
+ mode "644"
+ variables :master => interface, :slave => slave
+ notifies :run, "notify_group[networkctl-reload]"
+ end
+ end
+ end
+
+ template "/etc/systemd/network/10-#{interface[:interface]}.network" do
+ source "network.erb"
+ owner "root"
+ group "root"
+ mode "644"
+ variables :interface => interface
+ notifies :run, "notify_group[networkctl-reload]"
+ end
end
-file "/etc/netplan/99-chef.yaml" do
- owner "root"
- group "root"
- mode "644"
- content YAML.dump(netplan)
+package "systemd-resolved" do
+ action :install
+ only_if { platform?("ubuntu") && node[:lsb][:release].to_f > 22.04 || platform?("debian") && node[:lsb][:release].to_f > 11.0 }
end
-package "cloud-init" do
- action :purge
+service "systemd-networkd" do
+ action [:enable, :start]
end
if node[:networking][:wireguard][:enabled]
package "wireguard-tools" do
compile_time true
+ options "--no-install-recommends"
end
directory "/var/lib/systemd/wireguard" do
next if gateway.name == node.name
next unless gateway[:networking][:wireguard] && gateway[:networking][:wireguard][:enabled]
- allowed_ips = gateway.interfaces(:role => :internal).map do |interface|
- "#{interface[:network]}/#{interface[:prefix]}"
- end
+ allowed_ips = gateway.ipaddresses(:role => :internal).map(&:subnet)
node.default[:networking][:wireguard][:peers] << {
:public_key => gateway[:networking][:wireguard][:public_key],
}
end
- search(:node, "roles:mail OR roles:prometheus") do |server|
- allowed_ips = server.interfaces(:role => :internal).map do |interface|
- "#{interface[:network]}/#{interface[:prefix]}"
- end
+ search(:node, "roles:prometheus") do |server|
+ allowed_ips = server.ipaddresses(:role => :internal).map(&:subnet)
if server[:networking][:private_address]
allowed_ips << "#{server[:networking][:private_address]}/32"
:allowed_ips => "10.0.16.1/32",
:endpoint => "gate.compton.nu:51820"
}
+
+ # Grant home
+ node.default[:networking][:wireguard][:peers] << {
+ :public_key => "RofATnvlWxP3mt87+QKRXFE5MVxtoCcTsJ+yftZYEE4=",
+ :allowed_ips => "10.89.122.1/32",
+ :endpoint => "gate.firefishy.com:51820"
+ }
+
+ # Grant roaming
+ node.default[:networking][:wireguard][:peers] << {
+ :public_key => "YbUkREE9TAmomqgL/4Fh2e5u2Hh7drN/2o5qg3ndRxg=",
+ :allowed_ips => "10.89.123.1/32",
+ :endpoint => "roaming.firefishy.com:51820"
+ }
+ elsif node[:roles].include?("shenron")
+ search(:node, "roles:gateway") do |gateway|
+ allowed_ips = gateway.ipaddresses(:role => :internal).map(&:subnet)
+
+ node.default[:networking][:wireguard][:peers] << {
+ :public_key => gateway[:networking][:wireguard][:public_key],
+ :allowed_ips => allowed_ips,
+ :endpoint => "#{gateway.name}:51820"
+ }
+ end
+ end
+
+ file "/etc/systemd/network/wireguard.netdev" do
+ action :delete
end
- template "/etc/systemd/network/wireguard.netdev" do
+ template "/etc/systemd/network/10-wg0.netdev" do
source "wireguard.netdev.erb"
owner "root"
group "systemd-network"
mode "640"
+ notifies :run, "execute[networkctl-delete-wg0]"
+ notifies :run, "notify_group[networkctl-reload]"
+ end
+
+ file "/etc/systemd/network/wireguard.network" do
+ action :delete
end
- template "/etc/systemd/network/wireguard.network" do
+ template "/etc/systemd/network/10-wg0.network" do
source "wireguard.network.erb"
owner "root"
group "root"
mode "644"
+ notifies :run, "execute[networkctl-reload]"
end
- if node[:lsb][:release].to_f < 20.04
- execute "ip-link-delete-wg0" do
- action :nothing
- command "ip link delete wg0"
- subscribes :run, "template[/etc/systemd/network/wireguard.netdev]"
- only_if { ::File.exist?("/sys/class/net/wg0") }
- end
+ execute "networkctl-delete-wg0" do
+ action :nothing
+ command "networkctl delete wg0"
+ only_if { ::File.exist?("/sys/class/net/wg0") }
+ end
+end
- service "systemd-networkd" do
- action :nothing
- subscribes :restart, "template[/etc/systemd/network/wireguard.netdev]"
- subscribes :restart, "template[/etc/systemd/network/wireguard.network]"
- not_if { ENV.key?("TEST_KITCHEN") }
- end
- else
- execute "networkctl-delete-wg0" do
- action :nothing
- command "networkctl delete wg0"
- subscribes :run, "template[/etc/systemd/network/wireguard.netdev]"
- only_if { ::File.exist?("/sys/class/net/wg0") }
- end
+# Setup dokken network in systemd-networkd to avoid systemd-networkd-wait-online delay
+template "/etc/systemd/network/dokken.network" do
+ source "dokken.network.erb"
+ owner "root"
+ group "root"
+ mode "644"
+ notifies :run, "execute[networkctl-reload]", :immediately
+ only_if { kitchen? }
+end
- execute "networkctl-reload" do
- action :nothing
- command "networkctl reload"
- subscribes :run, "template[/etc/systemd/network/wireguard.netdev]"
- subscribes :run, "template[/etc/systemd/network/wireguard.network]"
- not_if { ENV.key?("TEST_KITCHEN") }
- end
- end
+notify_group "networkctl-reload"
+
+execute "networkctl-reload" do
+ action :nothing
+ command "networkctl reload"
+ subscribes :run, "notify_group[networkctl-reload]"
end
ohai "reload-hostname" do
execute "hostnamectl-set-hostname" do
command "hostnamectl set-hostname #{node[:networking][:hostname]}"
notifies :reload, "ohai[reload-hostname]"
- not_if { ENV.key?("TEST_KITCHEN") || node[:hostnamectl][:static_hostname] == node[:networking][:hostname] }
+ not_if { kitchen? || node[:hostnamectl][:static_hostname] == node[:networking][:hostname] }
end
template "/etc/hosts" do
owner "root"
group "root"
mode "644"
- not_if { ENV["TEST_KITCHEN"] }
+ not_if { kitchen? }
end
service "systemd-resolved" do
to "../run/systemd/resolve/stub-resolv.conf"
end
-zones = {}
+hosts = { :inet => [], :inet6 => [] }
search(:node, "networking:interfaces").collect do |n|
next if n[:fqdn] == node[:fqdn]
n.interfaces.each do |interface|
- next unless interface[:role] == "external" && interface[:zone]
+ next unless interface[:role] == "external"
- zones[interface[:zone]] ||= {}
- zones[interface[:zone]][interface[:family]] ||= []
- zones[interface[:zone]][interface[:family]] << interface[:address]
+ hosts[:inet] << interface[:inet][:address] if interface[:inet]
+ hosts[:inet6] << interface[:inet6][:address] if interface[:inet6]
end
end
-package "shorewall"
-
-template "/etc/default/shorewall" do
- source "shorewall-default.erb"
- owner "root"
- group "root"
- mode "644"
- notifies :restart, "service[shorewall]"
-end
+package "nftables"
-template "/etc/shorewall/shorewall.conf" do
- source "shorewall.conf.erb"
- owner "root"
- group "root"
- mode "644"
- notifies :restart, "service[shorewall]"
-end
+interfaces = []
-template "/etc/shorewall/zones" do
- source "shorewall-zones.erb"
- owner "root"
- group "root"
- mode "644"
- variables :type => "ipv4"
- notifies :restart, "service[shorewall]"
+node.interfaces(:role => :external).each do |interface|
+ interfaces << interface[:interface]
end
-template "/etc/shorewall/interfaces" do
- source "shorewall-interfaces.erb"
+template "/etc/nftables.conf" do
+ source "nftables.conf.erb"
owner "root"
group "root"
- mode "644"
- notifies :restart, "service[shorewall]"
+ mode "755"
+ variables :interfaces => interfaces, :hosts => hosts
+ notifies :reload, "service[nftables]"
end
-template "/etc/shorewall/hosts" do
- source "shorewall-hosts.erb"
+directory "/var/lib/nftables" do
owner "root"
group "root"
- mode "644"
- variables :zones => zones
- notifies :restart, "service[shorewall]"
+ mode "755"
end
-template "/etc/shorewall/conntrack" do
- source "shorewall-conntrack.erb"
+template "/usr/local/bin/nftables" do
+ source "nftables.erb"
owner "root"
group "root"
- mode "644"
- notifies :restart, "service[shorewall]"
- only_if { node[:networking][:firewall][:raw] }
+ mode "755"
end
-template "/etc/shorewall/policy" do
- source "shorewall-policy.erb"
- owner "root"
- group "root"
- mode "644"
- notifies :restart, "service[shorewall]"
+systemd_service "nftables-stop" do
+ action :delete
+ service "nftables"
+ dropin "stop"
end
-template "/etc/shorewall/rules" do
- source "shorewall-rules.erb"
- owner "root"
- group "root"
- mode "644"
- variables :family => "inet"
- notifies :restart, "service[shorewall]"
+systemd_service "nftables-chef" do
+ service "nftables"
+ dropin "chef"
+ exec_start "/usr/local/bin/nftables start"
+ exec_reload "/usr/local/bin/nftables reload"
+ exec_stop "/usr/local/bin/nftables stop"
end
if node[:networking][:firewall][:enabled]
- service "shorewall" do
+ service "nftables" do
action [:enable, :start]
- supports :restart => true
- status_command "shorewall status"
- ignore_failure true
end
else
- service "shorewall" do
+ service "nftables" do
action [:disable, :stop]
- supports :restart => true
- status_command "shorewall status"
- ignore_failure true
end
end
-template "/etc/logrotate.d/shorewall" do
- source "logrotate.shorewall.erb"
- owner "root"
- group "root"
- mode "644"
- variables :name => "shorewall"
-end
-
-firewall_rule "limit-icmp-echo" do
- action :accept
- family :inet
- source "net"
- dest "fw"
- proto "icmp"
- dest_ports "echo-request"
- rate_limit "s:1/sec:5"
-end
-
if node[:networking][:wireguard][:enabled]
- wireguard_source = if node[:roles].include?("gateway")
- "net"
- else
- "osm"
- end
-
firewall_rule "accept-wireguard" do
action :accept
- source wireguard_source
- dest "fw"
- proto "udp"
+ context :incoming
+ protocol :udp
+ source :osm unless node[:roles].include?("gateway")
dest_ports "51820"
source_ports "51820"
end
end
-if node[:roles].include?("gateway")
- template "/etc/shorewall/masq" do
- source "shorewall-masq.erb"
- owner "root"
- group "root"
- mode "644"
- notifies :restart, "service[shorewall]"
- end
-else
- file "/etc/shorewall/masq" do
- action :delete
- notifies :restart, "service[shorewall]"
- end
-end
-
-unless node.interfaces(:family => :inet6).empty?
- package "shorewall6"
-
- template "/etc/default/shorewall6" do
- source "shorewall-default.erb"
- owner "root"
- group "root"
- mode "644"
- notifies :restart, "service[shorewall6]"
- end
-
- template "/etc/shorewall6/shorewall6.conf" do
- source "shorewall6.conf.erb"
- owner "root"
- group "root"
- mode "644"
- notifies :restart, "service[shorewall6]"
- end
-
- template "/etc/shorewall6/zones" do
- source "shorewall-zones.erb"
- owner "root"
- group "root"
- mode "644"
- variables :type => "ipv6"
- notifies :restart, "service[shorewall6]"
- end
-
- template "/etc/shorewall6/interfaces" do
- source "shorewall6-interfaces.erb"
- owner "root"
- group "root"
- mode "644"
- notifies :restart, "service[shorewall6]"
- end
-
- template "/etc/shorewall6/hosts" do
- source "shorewall6-hosts.erb"
- owner "root"
- group "root"
- mode "644"
- variables :zones => zones
- notifies :restart, "service[shorewall6]"
- end
-
- template "/etc/shorewall6/conntrack" do
- source "shorewall-conntrack.erb"
- owner "root"
- group "root"
- mode "644"
- notifies :restart, "service[shorewall6]"
- only_if { node[:networking][:firewall][:raw] }
- end
-
- template "/etc/shorewall6/policy" do
- source "shorewall-policy.erb"
- owner "root"
- group "root"
- mode "644"
- notifies :restart, "service[shorewall6]"
- end
-
- template "/etc/shorewall6/rules" do
- source "shorewall-rules.erb"
- owner "root"
- group "root"
- mode "644"
- variables :family => "inet6"
- notifies :restart, "service[shorewall6]"
- end
-
- if node[:networking][:firewall][:enabled]
- service "shorewall6" do
- action [:enable, :start]
- supports :restart => true
- status_command "shorewall6 status"
- ignore_failure true
- end
- else
- service "shorewall6" do
- action [:disable, :stop]
- supports :restart => true
- status_command "shorewall6 status"
- ignore_failure true
- end
- end
-
- template "/etc/logrotate.d/shorewall6" do
- source "logrotate.shorewall.erb"
- owner "root"
- group "root"
- mode "644"
- variables :name => "shorewall6"
- end
-
- firewall_rule "limit-icmp6-echo" do
- action :accept
- family :inet6
- source "net"
- dest "fw"
- proto "ipv6-icmp"
- dest_ports "echo-request"
- rate_limit "s:1/sec:5"
- end
-end
-
-firewall_rule "accept-http" do
+firewall_rule "accept-http-osm" do
action :accept
- source "net"
- dest "fw"
- proto "tcp:syn"
- dest_ports "http"
- rate_limit node[:networking][:firewall][:http_rate_limit]
- connection_limit node[:networking][:firewall][:http_connection_limit]
+ context :incoming
+ protocol :tcp
+ source :osm
+ dest_ports %w[http https]
end
-firewall_rule "accept-https" do
+firewall_rule "accept-http" do
action :accept
- source "net"
- dest "fw"
- proto "tcp:syn"
- dest_ports "https"
+ context :incoming
+ protocol :tcp
+ dest_ports %w[http https]
rate_limit node[:networking][:firewall][:http_rate_limit]
connection_limit node[:networking][:firewall][:http_connection_limit]
end
# limitations under the License.
#
+require "ipaddr"
+
resource_name :firewall_rule
provides :firewall_rule
default_action :nothing
property :rule, :kind_of => String, :name_property => true
-property :family, :kind_of => [String, Symbol]
-property :source, :kind_of => String, :required => true
-property :dest, :kind_of => String, :required => true
-property :proto, :kind_of => String, :required => true
-property :dest_ports, :kind_of => [String, Integer], :default => "-"
-property :source_ports, :kind_of => [String, Integer], :default => "-"
-property :rate_limit, :kind_of => String, :default => "-"
-property :connection_limit, :kind_of => [String, Integer], :default => "-"
-property :helper, :kind_of => String, :default => "-"
+property :context, :kind_of => Symbol, :required => true, :is => [:incoming, :outgoing]
+property :protocol, :kind_of => Symbol, :required => true, :is => [:udp, :tcp]
+property :source, :kind_of => [String, Symbol, Array]
+property :dest, :kind_of => [String, Symbol, Array]
+property :dest_ports, :kind_of => [String, Integer, Array]
+property :source_ports, :kind_of => [String, Integer, Array]
+property :rate_limit, :kind_of => String
+property :connection_limit, :kind_of => [String, Integer]
+property :helper, :kind_of => String
property :compile_time, TrueClass, :default => true
action :accept do
- add_rule :accept
+ add_rule(:accept, "ip")
+ add_rule(:accept, "ip6")
end
action :drop do
- add_rule :drop
+ add_rule(:drop, "ip")
+ add_rule(:drop, "ip6")
end
action :reject do
- add_rule :reject
+ add_rule(:reject, "ip")
+ add_rule(:reject, "ip6")
end
action_class do
- def add_rule(action)
- rule = {
- :action => action.to_s.upcase,
- :source => new_resource.source,
- :dest => new_resource.dest,
- :proto => new_resource.proto,
- :dest_ports => new_resource.dest_ports.to_s,
- :source_ports => new_resource.source_ports.to_s,
- :rate_limit => new_resource.rate_limit,
- :connection_limit => new_resource.connection_limit.to_s,
- :helper => new_resource.helper
- }
-
- if new_resource.family.nil?
- node.default[:networking][:firewall][:inet] << rule
- node.default[:networking][:firewall][:inet6] << rule
- elsif new_resource.family.to_s == "inet"
- node.default[:networking][:firewall][:inet] << rule
- elsif new_resource.family.to_s == "inet6"
- node.default[:networking][:firewall][:inet6] << rule
+ def add_rule(action, ip)
+ rule = []
+
+ protocol = new_resource.protocol.to_s
+
+ source = addresses(new_resource.source, ip)
+ dest = addresses(new_resource.dest, ip)
+
+ return if new_resource.source && source.empty?
+ return if new_resource.dest && dest.empty?
+
+ rule << "#{protocol} sport #{format_ports(new_resource.source_ports)}" if new_resource.source_ports
+ rule << "#{protocol} dport #{format_ports(new_resource.dest_ports)}" if new_resource.dest_ports
+ rule << "#{ip} saddr #{format_addresses(source, ip)}" if new_resource.source
+ rule << "#{ip} daddr #{format_addresses(dest, ip)}" if new_resource.dest
+ rule << "ct state new" if new_resource.protocol == :tcp
+
+ if new_resource.connection_limit
+ set = "connlimit-#{new_resource.rule}-#{ip}"
+
+ node.default[:networking][:firewall][:sets] << {
+ :name => set, :type => set_type(ip), :flags => %w[dynamic]
+ }
+
+ rule << "add @#{set} { #{ip} saddr ct count #{new_resource.connection_limit} }"
+ end
+
+ if new_resource.rate_limit =~ %r{^s:(\d+)/sec:(\d+)$}
+ set = "ratelimit-#{new_resource.rule}-#{ip}"
+ rate = Regexp.last_match(1)
+ burst = Regexp.last_match(2)
+
+ node.default[:networking][:firewall][:sets] << {
+ :name => set, :type => set_type(ip), :flags => %w[dynamic], :timeout => 120
+ }
+
+ rule << "update @#{set} { #{ip} saddr limit rate #{rate}/second burst #{burst} packets }"
+ end
+
+ if new_resource.helper
+ helper = "#{new_resource.rule}-#{new_resource.helper}"
+
+ node.default[:networking][:firewall][:helpers] << {
+ :name => helper, :helper => new_resource.helper, :protocol => protocol
+ }
+
+ rule << "ct helper set #{helper}"
+ end
+
+ rule << case action
+ when :accept then "accept"
+ when :drop then "jump log-and-drop"
+ when :reject then "jump log-and-reject"
+ end
+
+ node.default[:networking][:firewall][new_resource.context] << rule.join(" ")
+ end
+
+ def addresses(addresses, ip)
+ if addresses.is_a?(Symbol)
+ addresses
else
- log "Unsupported network family" do
- level :error
- end
+ Array(addresses).map do |address|
+ if ip == "ip" && IPAddr.new(address.to_s).ipv4?
+ address
+ elsif ip == "ip6" && IPAddr.new(address.to_s).ipv6?
+ address
+ end
+ end.compact
+ end
+ end
+
+ def format_ports(ports)
+ "{ #{Array(ports).map(&:to_s).join(', ')} }"
+ end
+
+ def format_addresses(addresses, ip)
+ if addresses.is_a?(Symbol)
+ "@#{ip}-#{addresses}-addresses"
+ else
+ "{ #{Array(addresses).map(&:to_s).join(', ')} }"
+ end
+ end
+
+ def set_type(ip)
+ case ip
+ when "ip" then "ipv4_addr"
+ when "ip6" then "ipv6_addr"
end
end
end
--- /dev/null
+[NetDev]
+Name=<%= @interface[:interface] %>
+Kind=bond
+
+[Bond]
+Mode=<%= @interface[:bond][:mode] || "active-backup" %>
+<% if @interface[:bond][:xmithashpolicy] -%>
+TransmitHashPolicy=<%= @interface[:bond][:xmithashpolicy] %>
+<% end -%>
+<% if @interface[:bond][:lacprate] -%>
+LACPTransmitRate=<%= @interface[:bond][:lacprate] %>
+<% end -%>
+MIIMonitorSec=<%= @interface[:bond][:miimon] || "100ms" %>
+UpDelaySec=<%= @interface[:bond][:updelay] || "200ms" %>
+DownDelaySec=<%= @interface[:bond][:downdelay] || "200ms" %>
--- /dev/null
+[Match]
+Name=eth0
+
+[Link]
+RequiredForOnline=routable
+
+[Network]
+DHCP=no
+LinkLocalAddressing=no
+KeepConfiguration=yes
--- /dev/null
+[Match]
+Name=<%= @interface[:interface] %>
+
+[Network]
+<% if @interface.dig(:inet6, :dhcp) -%>
+DHCP=ipv6
+<% end -%>
+<% if @interface[:inet] -%>
+Address=<%= @interface[:inet][:address] %>/<%== @interface[:inet][:prefix] %>
+<% end -%>
+<% if @interface[:inet6] -%>
+Address=<%= @interface[:inet6][:address] %>/<%== @interface[:inet6][:prefix] %>
+<% end -%>
+IPv6AcceptRA=no
+<% Array(@interface[:vlans]).sort.uniq.each do |vlan| -%>
+VLAN=<%= @interface[:interface] %>.<%= vlan %>
+<% end -%>
+<% if @interface.dig(:inet6, :dhcp) -%>
+
+[DHCPv6]
+<% if @interface[:inet6][:dhcp][:duidtype] -%>
+DUIDType=<%= @interface[:inet6][:dhcp][:duidtype] %>
+<% end -%>
+<% if @interface[:inet6][:dhcp][:duidrawdata] -%>
+DUIDRawData=<%= @interface[:inet6][:dhcp][:duidrawdata] %>
+<% end -%>
+WithoutRA=solicit
+<% end -%>
+<% if @interface.dig(:inet, :gateway) && @interface[:inet][:gateway] != @interface[:inet][:address] -%>
+
+[Route]
+Gateway=<%= @interface[:inet][:gateway] %>
+GatewayOnLink=true
+<% if @interface[:metric] -%>
+Metric=<%= @interface[:metric] %>
+<% end -%>
+<% if @interface[:source_route_table] -%>
+
+[Route]
+Gateway=<%= @interface[:inet][:gateway] %>
+GatewayOnLink=true
+<% if @interface[:metric] -%>
+Metric=<%= @interface[:metric] %>
+<% end -%>
+Table=<%= @interface[:source_route_table] %>
+
+[RoutingPolicyRule]
+From=<%= @interface[:inet][:address] %>
+Table=<%= @interface[:source_route_table] %>
+<% end -%>
+<% end -%>
+<% if @interface.dig(:inet6, :gateway) && @interface[:inet6][:gateway] != @interface[:inet6][:address] -%>
+
+[Route]
+Gateway=<%= @interface[:inet6][:gateway] %>
+GatewayOnLink=true
+<% if @interface[:metric] -%>
+Metric=<%= @interface[:metric] %>
+<% end -%>
+<% if @interface[:source_route_table] -%>
+
+[Route]
+Gateway=<%= @interface[:inet6][:gateway] %>
+GatewayOnLink=true
+<% if @interface[:metric] -%>
+Metric=<%= @interface[:metric] %>
+<% end -%>
+Table=<%= @interface[:source_route_table] %>
+
+[RoutingPolicyRule]
+From=<%= @interface[:inet6][:address] %>
+Table=<%= @interface[:source_route_table] %>
+<% end -%>
+<% end -%>
+<% Hash(@interface.dig(:inet, :routes)).sort.each do |destination, details| -%>
+<% unless details[:via] == @interface[:inet][:address] -%>
+
+[Route]
+<% if details[:via] -%>
+Gateway=<%= details[:via] %>
+<% end -%>
+Destination=<%= destination %>
+<% if details[:metric] -%>
+Metric=<%= details[:metric] %>
+<% end -%>
+<% if details[:type] -%>
+Type=<%= details[:type] %>
+<% end -%>
+<% end -%>
+<% end -%>
+<% Hash(@interface.dig(:inet6, :routes)).sort.each do |destination, details| -%>
+<% unless details[:via] == @interface[:inet6][:address] -%>
+
+[Route]
+<% if details[:via] -%>
+Gateway=<%= details[:via] %>
+<% end -%>
+Destination=<%= destination %>
+<% if details[:metric] -%>
+Metric=<%= details[:metric] %>
+<% end -%>
+<% if details[:type] -%>
+Type=<%= details[:type] %>
+<% end -%>
+<% end -%>
+<% end -%>
--- /dev/null
+#!/usr/sbin/nft -f
+
+<% unless @interfaces.empty? -%>
+define external-interfaces = { <%= @interfaces.sort.uniq.join(", ") %> }
+<% end -%>
+
+define ip-private-addresses = { 0.0.0.0, 10.0.0.0/8, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.2.0/24, 192.168.0.0/16 }
+define ip-multicast-addresses = { 224.0.0.0/4 }
+define ip6-private-addresses = { 2001:db8::/32, fc00::/7 }
+define ip6-multicast-addresses = { ff00::/8 }
+
+table inet chef-filter {
+ set ip-osm-addresses {
+ type ipv4_addr
+<% unless Array(@hosts[:inet]).empty? -%>
+ elements = { <%= Array(@hosts[:inet]).sort.join(", ") %> }
+<% end -%>
+ }
+
+ set ip6-osm-addresses {
+ type ipv6_addr
+<% unless Array(@hosts[:inet6]).empty? -%>
+ elements = { <%= Array(@hosts[:inet6]).sort.join(", ") %> }
+<% end -%>
+ }
+
+ set ip-blocklist {
+ type ipv4_addr
+ flags interval
+ }
+
+ set ip6-blocklist {
+ type ipv6_addr
+ flags interval
+ }
+
+ set ratelimit-icmp-echo-ip {
+ type ipv4_addr
+ flags dynamic
+ timeout 120s
+ }
+
+ set ratelimit-icmp-echo-ip6 {
+ type ipv6_addr
+ flags dynamic
+ timeout 120s
+ }
+
+<% node[:networking][:firewall][:sets].each do |set| -%>
+ set <%= set[:name] %> {
+ type <%= set[:type] %>
+<% if set[:flags] -%>
+ flags <%= set[:flags].join(", ") %>
+<% end -%>
+<% if set[:timeout] -%>
+ timeout <%= set[:timeout] %>s
+<% end -%>
+ }
+
+<% end -%>
+
+<% node[:networking][:firewall][:helpers].each do |helper| -%>
+ ct helper <%= helper[:name] %> {
+ type "<%= helper[:helper] %>" protocol <%= helper[:protocol] %>
+ }
+
+<% end -%>
+ chain log-and-drop {
+ limit rate 1/second log
+ drop
+ }
+
+ chain log-and-reject {
+ limit rate 1/second log
+ reject
+ }
+
+ chain incoming {
+<% if node[:networking][:firewall][:allowlist].empty? -%>
+ ip saddr { $ip-private-addresses, $ip-multicast-addresses } jump log-and-drop
+<% else -%>
+ ip saddr { $ip-private-addresses, $ip-multicast-addresses } ip saddr != { <%= node[:networking][:firewall][:allowlist].sort.join(", ") %> } jump log-and-drop
+<% end -%>
+ ip6 saddr { $ip6-private-addresses, $ip6-multicast-addresses } jump log-and-drop
+
+ ip saddr @ip-blocklist jump log-and-drop
+ ip6 saddr @ip6-blocklist jump log-and-drop
+
+ icmp type { echo-request } update @ratelimit-icmp-echo-ip { ip saddr limit rate 1/second } accept
+ icmp type { echo-request } drop
+
+ icmpv6 type { nd-neighbor-solicit, nd-neighbor-advert, nd-router-solicit, nd-router-advert } accept
+ icmpv6 type { echo-request } update @ratelimit-icmp-echo-ip6 { ip6 saddr limit rate 1/second } accept
+ icmpv6 type { echo-request } drop
+
+ ct state { established, related } accept
+
+ meta l4proto { icmp, icmpv6 } jump log-and-drop
+
+ tcp flags & (fin|syn|rst|psh|ack|urg) == fin|psh|urg jump log-and-drop
+ tcp flags & (fin|syn|rst|psh|ack|urg) == 0x0 jump log-and-drop
+ tcp flags & (syn|rst) == syn|rst jump log-and-drop
+ tcp flags & (fin|rst) == fin|rst jump log-and-drop
+ tcp flags & (fin|syn) == fin|syn jump log-and-drop
+ tcp flags & (fin|psh|ack) == fin|psh jump log-and-drop
+ tcp sport 0 tcp flags & (fin|syn|rst|ack) == syn jump log-and-drop
+
+<% node[:networking][:firewall][:incoming].uniq.each do |rule| -%>
+ <%= rule %>
+<% end -%>
+
+ jump log-and-drop
+ }
+
+ chain outgoing {
+<% if node[:networking][:firewall][:allowlist].empty? -%>
+ ip daddr { $ip-private-addresses } jump log-and-drop
+<% else -%>
+ ip daddr { $ip-private-addresses } ip daddr != { <%= node[:networking][:firewall][:allowlist].sort.join(", ") %> } jump log-and-drop
+<% end -%>
+ ip6 daddr { $ip6-private-addresses } jump log-and-drop
+
+<% node[:networking][:firewall][:outgoing].each do |rule| -%>
+ <%= rule %>
+<% end -%>
+
+ accept
+ }
+
+ chain input {
+ type filter hook input priority filter;
+
+<% unless @interfaces.empty? -%>
+ iifname { $external-interfaces } jump incoming
+<% end -%>
+
+ accept
+ }
+
+ chain forward {
+ type filter hook forward priority filter;
+
+<% unless @interfaces.empty? -%>
+ iifname { $external-interfaces } jump incoming
+ oifname { $external-interfaces } jump outgoing
+<% end -%>
+
+ accept
+ }
+
+ chain output {
+ type filter hook output priority filter;
+
+<% unless @interfaces.empty? -%>
+ oifname { $external-interfaces } jump outgoing
+<% end -%>
+
+ accept
+ }
+}
+<% if node[:roles].include?("gateway") -%>
+
+table ip chef-nat {
+ chain postrouting {
+ type nat hook postrouting priority srcnat;
+
+<% node.interfaces(:role => :external).each do |external| -%>
+<% node.ipaddresses(:role => :internal, :family => :inet).each do |internal| -%>
+ oifname { <%= external[:interface] %> } ip saddr { <%= internal.subnet %> } snat <%= external[:inet][:address] %>
+<% end -%>
+<% end -%>
+ }
+}
+<% end -%>
--- /dev/null
+#!/bin/sh -e
+
+start() {
+ /usr/sbin/nft -f /etc/nftables.conf
+ [ -f /var/lib/nftables/ip-blocklist.nft ] && /usr/sbin/nft -f /var/lib/nftables/ip-blocklist.nft || :
+ [ -f /var/lib/nftables/ip6-blocklist.nft ] && /usr/sbin/nft -f /var/lib/nftables/ip6-blocklist.nft || :
+}
+
+stop() {
+ /usr/sbin/nft list set inet chef-filter ip-blocklist > /var/lib/nftables/ip-blocklist.nft
+ /usr/sbin/nft list set inet chef-filter ip6-blocklist > /var/lib/nftables/ip6-blocklist.nft
+ /usr/sbin/nft delete table inet chef-filter
+<% if node[:roles].include?("gateway") -%>
+ /usr/sbin/nft delete table ip chef-nat
+<% end -%>
+}
+
+reload() {
+ stop
+ start
+}
+
+block() {
+ for address in "$@"
+ do
+ case "$address" in
+ *.*) /usr/sbin/nft --check add element inet chef-filter ip-blocklist "{ $address }" && /usr/sbin/nft add element inet chef-filter ip-blocklist "{ $address }" ;;
+ *:*) /usr/sbin/nft --check add element inet chef-filter ip6-blocklist "{ $address }" && /usr/sbin/nft add element inet chef-filter ip6-blocklist "{ $address }" ;;
+ esac
+ done
+}
+
+unblock() {
+ for address in "$@"
+ do
+ case "$address" in
+ *.*) /usr/sbin/nft --check delete element inet chef-filter ip-blocklist "{ $address }" && /usr/sbin/nft delete element inet chef-filter ip-blocklist "{ $address }" ;;
+ *:*) /usr/sbin/nft --check delete element inet chef-filter ip6-blocklist "{ $address }" && /usr/sbin/nft delete element inet chef-filter ip6-blocklist "{ $address }" ;;
+ esac
+ done
+}
+
+flush() {
+ /usr/sbin/nft --check flush set inet chef-filter ip-blocklist && /usr/sbin/nft flush set inet chef-filter ip-blocklist
+ /usr/sbin/nft --check flush set inet chef-filter ip6-blocklist && /usr/sbin/nft flush set inet chef-filter ip6-blocklist
+}
+
+command=$1
+shift
+
+case "$command" in
+ start) start;;
+ stop) stop;;
+ reload) reload;;
+ block) block "$@";;
+ unblock) unblock "$@";;
+ flush) flush;;
+esac
+
+exit 0
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-?FORMAT 3
-
-# ACTION SOURCE DEST PROTO DPORT SPORT USER SWITCH
-NOTRACK:P lo - - - - - -
-NOTRACK:O - lo - - - - -
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-# Allow shorewall to start
-startup=1
-
-# Program options
-OPTIONS=""
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-# ZONE HOST OPTIONS
-<% node.interfaces(:family => :inet, :role => :external).each do |interface| -%>
-<% if interface[:interface] -%>
-<% @zones.keys.sort.each do |zone| -%>
-<% if @zones[zone]["inet"] -%>
-<% @zones[zone]["inet"].sort.each do |ra| -%>
-<%= zone %> <%= interface[:interface] %>:<%= ra %>
-<% end -%>
-<% end -%>
-<% end -%>
-<% end -%>
-<% end -%>
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-?FORMAT 2
-
-# ZONE INTERFACE OPTIONS
-<% node[:networking][:interfaces].each do |name,interface| -%>
-<% if interface[:interface] && interface[:family] == "inet" -%>
-<% if interface[:role] == "internal" -%>
-loc <%= interface[:interface] %> nosmurfs,tcpflags
-<% elsif interface[:role] == "external" -%>
-net <%= interface[:interface] %> nosmurfs,tcpflags
-<% end -%>
-<% end -%>
-<% end -%>
-loc wg+ nosmurfs,tcpflags
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-# INTERFACE SOURCE ADDRESS
-<% node.interfaces(:role => :external).each do |external| -%>
-<% node.interfaces(:role => :internal).each do |internal| -%>
-<%= external[:interface] %> <%= internal[:network] %>/<%= internal[:prefix] %> detect
-<% end -%>
-<% end -%>
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-# FROM TO POLICY LOG LEVEL BURST:LIMIT
-net all DROP
-all all ACCEPT
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-?SECTION NEW
-
-# ACTION SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE USER/ MARK CONNLIMIT TIME HEADERS SWITCH HELPER
-# PORTS PORTS DEST LIMIT GROUP
-<% node[:networking][:firewall][@family].each do |r| # ~FC034 -%>
-<%= r[:action] %> <%= r[:source] %> <%= r[:dest] %> <%= r[:proto] %> <%= r[:dest_ports] %> <%= r[:source_ports] %> - <%= r[:rate_limit] %> - - <%= r[:connection_limit] %> - - - <%= r[:helper] %>
-<% end -%>
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-# ZONE TYPE OPTIONS IN OPTIONS OUT OPTIONS
-fw firewall
-loc <%= @type %>
-net <%= @type %>
-osm:net <%= @type %>
-ucl:osm <%= @type %>
-ams:osm <%= @type %>
-bm:osm <%= @type %>
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-###############################################################################
-# S T A R T U P E N A B L E D
-###############################################################################
-
-STARTUP_ENABLED=Yes
-
-###############################################################################
-# V E R B O S I T Y
-###############################################################################
-
-VERBOSITY=1
-
-###############################################################################
-# P A G E R
-###############################################################################
-
-PAGER=
-
-###############################################################################
-# F I R E W A L L
-###############################################################################
-
-FIREWALL=
-
-###############################################################################
-# L O G G I N G
-###############################################################################
-
-<% if node[:networking][:firewall][:log] -%>
-LOG_LEVEL="info"
-<% else -%>
-LOG_LEVEL="none"
-<% end -%>
-
-BLACKLIST_LOG_LEVEL=
-
-INVALID_LOG_LEVEL=
-
-LOG_BACKEND=
-
-LOG_MARTIANS=Yes
-
-LOG_VERBOSITY=2
-
-LOGALLNEW=
-
-LOGFILE=/var/log/messages
-
-LOGFORMAT="%s %s "
-
-LOGTAGONLY=No
-
-LOGLIMIT="s:1/sec:10"
-
-MACLIST_LOG_LEVEL="$LOG_LEVEL"
-
-RELATED_LOG_LEVEL=
-
-RPFILTER_LOG_LEVEL="$LOG_LEVEL"
-
-SFILTER_LOG_LEVEL="$LOG_LEVEL"
-
-SMURF_LOG_LEVEL="$LOG_LEVEL"
-
-STARTUP_LOG=/var/log/shorewall-init.log
-
-TCP_FLAGS_LOG_LEVEL="$LOG_LEVEL"
-
-UNTRACKED_LOG_LEVEL=
-
-###############################################################################
-# L O C A T I O N O F F I L E S A N D D I R E C T O R I E S
-###############################################################################
-
-ARPTABLES=
-
-CONFIG_PATH=":${CONFDIR}/shorewall:${SHAREDIR}/shorewall"
-
-GEOIPDIR=/usr/share/xt_geoip/LE
-
-IPTABLES=
-
-IP=
-
-IPSET=
-
-LOCKFILE=
-
-MODULESDIR=
-
-NFACCT=
-
-PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin
-
-PERL=/usr/bin/perl
-
-RESTOREFILE=restore
-
-SHOREWALL_SHELL=/bin/sh
-
-SUBSYSLOCK=""
-
-TC=
-
-###############################################################################
-# D E F A U L T A C T I O N S / M A C R O S
-###############################################################################
-
-ACCEPT_DEFAULT="none"
-BLACKLIST_DEFAULT="Broadcast(DROP),Multicast(DROP),dropNotSyn:$LOG_LEVEL,dropInvalid:$LOG_LEVEL,DropDNSrep:$LOG_LEVEL"
-DROP_DEFAULT="Broadcast(DROP),Multicast(DROP)"
-NFQUEUE_DEFAULT="none"
-QUEUE_DEFAULT="none"
-REJECT_DEFAULT="Broadcast(DROP),Multicast(DROP)"
-
-###############################################################################
-# R S H / R C P C O M M A N D S
-###############################################################################
-
-RCP_COMMAND='scp ${files} ${root}@${system}:${destination}'
-RSH_COMMAND='ssh ${root}@${system} ${command}'
-
-###############################################################################
-# F I R E W A L L O P T I O N S
-###############################################################################
-
-ACCOUNTING=Yes
-
-ACCOUNTING_TABLE=filter
-
-ADD_IP_ALIASES=No
-
-ADD_SNAT_ALIASES=No
-
-ADMINISABSENTMINDED=Yes
-
-AUTOCOMMENT=Yes
-
-AUTOHELPERS=Yes
-
-AUTOMAKE=Yes
-
-BALANCE_PROVIDERS=No
-
-BASIC_FILTERS=No
-
-<% if node[:networking][:firewall][:raw] -%>
-BLACKLIST="NEW,INVALID,UNTRACKED"
-<% else -%>
-BLACKLIST="NEW,INVALID"
-<% end -%>
-
-CLAMPMSS=No
-
-CLEAR_TC=Yes
-
-COMPLETE=No
-
-DEFER_DNS_RESOLUTION=Yes
-
-DELETE_THEN_ADD=Yes
-
-DETECT_DNAT_IPADDRS=No
-
-DISABLE_IPV6=No
-
-DOCKER=No
-
-DONT_LOAD=
-
-DYNAMIC_BLACKLIST=Yes
-
-EXPAND_POLICIES=Yes
-
-EXPORTMODULES=Yes
-
-FASTACCEPT=No
-
-FORWARD_CLEAR_MARK=
-
-HELPERS=
-
-IGNOREUNKNOWNVARIABLES=No
-
-IMPLICIT_CONTINUE=No
-
-INLINE_MATCHES=No
-
-IPSET_WARNINGS=Yes
-
-IP_FORWARDING=Keep
-
-KEEP_RT_TABLES=No
-
-LOAD_HELPERS_ONLY=Yes
-
-MACLIST_TABLE=filter
-
-MACLIST_TTL=
-
-MANGLE_ENABLED=Yes
-
-MAPOLDACTIONS=No
-
-MARK_IN_FORWARD_CHAIN=No
-
-MINIUPNPD=No
-
-MULTICAST=No
-
-MUTEX_TIMEOUT=60
-
-NULL_ROUTE_RFC1918=No
-
-OPTIMIZE=All
-
-OPTIMIZE_ACCOUNTING=No
-
-PERL_HASH_SEED=0
-
-REJECT_ACTION=
-
-REQUIRE_INTERFACE=No
-
-RESTART=restart
-
-RESTORE_DEFAULT_ROUTE=Yes
-
-RESTORE_ROUTEMARKS=Yes
-
-RETAIN_ALIASES=No
-
-ROUTE_FILTER=Yes
-
-SAVE_ARPTABLES=No
-
-SAVE_IPSETS=No
-
-<% if node[:networking][:firewall][:mangle] -%>
-TC_ENABLED=Internal
-<% else -%>
-TC_ENABLED=No
-<% end -%>
-
-TC_EXPERT=No
-
-TC_PRIOMAP="2 3 3 3 2 3 1 1 2 2 2 2 2 2 2 2"
-
-TRACK_PROVIDERS=Yes
-
-TRACK_RULES=No
-
-USE_DEFAULT_RT=No
-
-USE_NFLOG_SIZE=No
-
-USE_PHYSICAL_NAMES=No
-
-USE_RT_NAMES=No
-
-VERBOSE_MESSAGES=Yes
-
-WARNOLDCAPVERSION=Yes
-
-WORKAROUNDS=No
-
-ZERO_MARKS=No
-
-ZONE2ZONE=-
-
-###############################################################################
-# P A C K E T D I S P O S I T I O N
-###############################################################################
-
-BLACKLIST_DISPOSITION=DROP
-
-INVALID_DISPOSITION=CONTINUE
-
-MACLIST_DISPOSITION=REJECT
-
-RELATED_DISPOSITION=ACCEPT
-
-RPFILTER_DISPOSITION=DROP
-
-SMURF_DISPOSITION=DROP
-
-SFILTER_DISPOSITION=DROP
-
-TCP_FLAGS_DISPOSITION=DROP
-
-UNTRACKED_DISPOSITION=CONTINUE
-
-################################################################################
-# P A C K E T M A R K L A Y O U T
-################################################################################
-
-TC_BITS=
-
-PROVIDER_BITS=
-
-PROVIDER_OFFSET=
-
-MASK_BITS=
-
-ZONE_BITS=0
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-# ZONE HOST OPTIONS
-<% node.interfaces(:family => :inet6, :role => :external).each do |interface| -%>
-<% @zones.keys.sort.each do |zone| -%>
-<% if @zones[zone]["inet6"] -%>
-<% @zones[zone]["inet6"].sort.each do |ra| -%>
-<%= zone %> <%= interface[:interface] %>:[<%= ra %>]
-<% end -%>
-<% end -%>
-<% end -%>
-<% end -%>
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-?FORMAT 2
-
-# ZONE INTERFACE OPTIONS
-<% node[:networking][:interfaces].each do |name,interface| -%>
-<% if interface[:family] == "inet6" -%>
-<% if interface[:role] == "internal" -%>
-loc <%= interface[:interface] %> -
-<% elsif interface[:role] == "external" -%>
-net <%= interface[:interface] %> -
-<% end -%>
-<% end -%>
-<% end -%>
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-###############################################################################
-# S T A R T U P E N A B L E D
-###############################################################################
-
-STARTUP_ENABLED=Yes
-
-###############################################################################
-# V E R B O S I T Y
-###############################################################################
-
-VERBOSITY=1
-
-###############################################################################
-# P A G E R
-###############################################################################
-
-PAGER=
-
-###############################################################################
-# F I R E W A L L
-###############################################################################
-
-FIREWALL=
-
-###############################################################################
-# L O G G I N G
-###############################################################################
-
-<% if node[:networking][:firewall][:log] -%>
-LOG_LEVEL="info"
-<% else -%>
-LOG_LEVEL="none"
-<% end -%>
-
-BLACKLIST_LOG_LEVEL=
-
-INVALID_LOG_LEVEL=
-
-LOG_BACKEND=
-
-LOG_VERBOSITY=2
-
-LOGALLNEW=
-
-LOGFILE=/var/log/messages
-
-LOGFORMAT="%s %s "
-
-LOGLIMIT="s:1/sec:10"
-
-LOGTAGONLY=No
-
-MACLIST_LOG_LEVEL="$LOG_LEVEL"
-
-RELATED_LOG_LEVEL=
-
-RPFILTER_LOG_LEVEL="$LOG_LEVEL"
-
-SFILTER_LOG_LEVEL="$LOG_LEVEL"
-
-SMURF_LOG_LEVEL="$LOG_LEVEL"
-
-STARTUP_LOG=/var/log/shorewall6-init.log
-
-TCP_FLAGS_LOG_LEVEL="$LOG_LEVEL"
-
-UNTRACKED_LOG_LEVEL=
-
-###############################################################################
-# L O C A T I O N O F F I L E S A N D D I R E C T O R I E S
-###############################################################################
-
-CONFIG_PATH=":${CONFDIR}/shorewall6:/usr/share/shorewall6:${SHAREDIR}/shorewall"
-
-GEOIPDIR=/usr/share/xt_geoip/LE
-
-IP6TABLES=
-
-IP=
-
-IPSET=
-
-LOCKFILE=
-
-MODULESDIR=
-
-NFACCT=
-
-PERL=/usr/bin/perl
-
-PATH="/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin"
-
-RESTOREFILE=restore
-
-SHOREWALL_SHELL=/bin/sh
-
-SUBSYSLOCK=""
-
-TC=
-
-###############################################################################
-# D E F A U L T A C T I O N S / M A C R O S
-###############################################################################
-
-ACCEPT_DEFAULT="none"
-BLACKLIST_DEFAULT="AllowICMPs,Broadcast(DROP),Multicast(DROP),dropNotSyn:$LOG_LEVEL,dropInvalid:$LOG_LEVEL,DropDNSrep:$LOG_LEVEL"
-DROP_DEFAULT="AllowICMPs,Broadcast(DROP),Multicast(DROP)"
-NFQUEUE_DEFAULT="none"
-QUEUE_DEFAULT="none"
-REJECT_DEFAULT="AllowICMPs,Broadcast(DROP),Multicast(DROP)"
-
-###############################################################################
-# R S H / R C P C O M M A N D S
-###############################################################################
-
-RCP_COMMAND='scp ${files} ${root}@${system}:${destination}'
-RSH_COMMAND='ssh ${root}@${system} ${command}'
-
-###############################################################################
-# F I R E W A L L O P T I O N S
-###############################################################################
-
-ACCOUNTING=Yes
-
-ACCOUNTING_TABLE=filter
-
-ADMINISABSENTMINDED=Yes
-
-AUTOCOMMENT=Yes
-
-AUTOHELPERS=Yes
-
-AUTOMAKE=Yes
-
-BALANCE_PROVIDERS=No
-
-BASIC_FILTERS=No
-
-<% if node[:networking][:firewall][:raw] -%>
-BLACKLIST="NEW,INVALID,UNTRACKED"
-<% else -%>
-BLACKLIST="NEW,INVALID"
-<% end -%>
-
-CLAMPMSS=No
-
-CLEAR_TC=No
-
-COMPLETE=No
-
-DEFER_DNS_RESOLUTION=Yes
-
-DELETE_THEN_ADD=Yes
-
-DONT_LOAD=
-
-DYNAMIC_BLACKLIST=Yes
-
-EXPAND_POLICIES=Yes
-
-EXPORTMODULES=Yes
-
-FASTACCEPT=No
-
-<% if node[:networking][:firewall][:mark] -%>
-FORWARD_CLEAR_MARK=Yes
-<% else -%>
-FORWARD_CLEAR_MARK=No
-<% end -%>
-
-HELPERS=
-
-IGNOREUNKNOWNVARIABLES=No
-
-IMPLICIT_CONTINUE=No
-
-INLINE_MATCHES=No
-
-IPSET_WARNINGS=Yes
-
-IP_FORWARDING=Keep
-
-KEEP_RT_TABLES=No
-
-LOAD_HELPERS_ONLY=Yes
-
-MACLIST_TABLE=filter
-
-MACLIST_TTL=
-
-MANGLE_ENABLED=Yes
-
-MARK_IN_FORWARD_CHAIN=No
-
-MINIUPNPD=No
-
-MUTEX_TIMEOUT=60
-
-OPTIMIZE=All
-
-OPTIMIZE_ACCOUNTING=No
-
-PERL_HASH_SEED=0
-
-REJECT_ACTION=
-
-REQUIRE_INTERFACE=No
-
-RESTART=restart
-
-RESTORE_DEFAULT_ROUTE=Yes
-
-RESTORE_ROUTEMARKS=Yes
-
-SAVE_IPSETS=No
-
-<% if node[:networking][:firewall][:mangle] -%>
-TC_ENABLED=Shared
-<% else -%>
-TC_ENABLED=No
-<% end -%>
-
-TC_EXPERT=No
-
-TC_PRIOMAP="2 3 3 3 2 3 1 1 2 2 2 2 2 2 2 2"
-
-TRACK_PROVIDERS=Yes
-
-TRACK_RULES=No
-
-USE_DEFAULT_RT=Yes
-
-USE_NFLOG_SIZE=No
-
-USE_PHYSICAL_NAMES=No
-
-USE_RT_NAMES=No
-
-VERBOSE_MESSAGES=Yes
-
-WARNOLDCAPVERSION=Yes
-
-WORKAROUNDS=No
-
-ZERO_MARKS=No
-
-ZONE2ZONE=
-
-###############################################################################
-# P A C K E T D I S P O S I T I O N
-###############################################################################
-
-BLACKLIST_DISPOSITION=DROP
-
-INVALID_DISPOSITION=CONTINUE
-
-MACLIST_DISPOSITION=REJECT
-
-RELATED_DISPOSITION=ACCEPT
-
-SFILTER_DISPOSITION=DROP
-
-RPFILTER_DISPOSITION=DROP
-
-SMURF_DISPOSITION=DROP
-
-TCP_FLAGS_DISPOSITION=DROP
-
-UNTRACKED_DISPOSITION=CONTINUE
-
-################################################################################
-# P A C K E T M A R K L A Y O U T
-################################################################################
-
-TC_BITS=
-
-PROVIDER_BITS=
-
-PROVIDER_OFFSET=
-
-MASK_BITS=
-
-ZONE_BITS=0
-
-#LAST LINE -- DO NOT REMOVE
--- /dev/null
+[Match]
+Name=<%= @slave %>
+
+[Link]
+RequiredForOnline=no
+
+[Network]
+LinkLocalAddressing=no
+IPv6AcceptRA=no
+Bond=<%= @master[:interface] %>
+<% if @master[:bond][:mode].nil? || @master[:bond][:mode] == "active-backup" -%>
+<% if @master[:bond][:slaves].first == @slave -%>
+PrimarySlave=true
+<% end -%>
+<% end -%>
--- /dev/null
+[NetDev]
+Name=<%= @interface[:interface] %>
+Kind=vlan
+
+[VLAN]
+Id=<%= @vlan %>
Kind=wireguard
[WireGuard]
-<% if node[:lsb][:release].to_f < 20.04 -%>
-PrivateKey=<%= IO.read("/var/lib/systemd/wireguard/private.key").chomp %>
-<% else -%>
PrivateKeyFile=/var/lib/systemd/wireguard/private.key
-<% end -%>
ListenPort=51820
<% node[:networking][:wireguard][:peers].sort_by { |p| p[:public_key] }.each do |peer| -%>
[WireGuardPeer]
PublicKey=<%= peer[:public_key] %>
-<% if node[:lsb][:release].to_f < 20.04 -%>
-PresharedKey=<%= IO.read("/var/lib/systemd/wireguard/preshared.key").chomp %>
-<% else -%>
PresharedKeyFile=/var/lib/systemd/wireguard/preshared.key
-<% end -%>
AllowedIPs=<%= Array(peer[:allowed_ips]).sort.join(",") %>
<% if peer[:endpoint] -%>
Endpoint=<%= peer[:endpoint] %>
+++ /dev/null
-# NFS Cookbook
-
-This cookbook configures NFS (the Network File System) which is used on
-various servers. There are two recipes:
-
-* default: configures NFS clients based on node attributes.
-* server: configures the central NFS server.
+++ /dev/null
-default[:nfs] = {}
+++ /dev/null
-#
-# Cookbook:: nfs
-# Recipe:: default
-#
-# Copyright:: 2010, OpenStreetMap Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-package "nfs-common"
-
-node[:nfs].each do |mountpoint, details|
- mount_options = if details[:readonly]
- "ro,bg,soft,tcp,rsize=8192,wsize=8192,nfsvers=4"
- else
- "rw,bg,tcp,rsize=8192,wsize=8192,nfsvers=4"
- end
-
- directory mountpoint do
- owner "root"
- group "root"
- mode "755"
- recursive true
- not_if { ::File.exist?(mountpoint) }
- end
-
- mount mountpoint do
- action [:mount, :enable]
- device "#{details[:host]}:#{details[:path]}"
- fstype "nfs"
- options mount_options
- ignore_failure true
- end
-end
+++ /dev/null
-#
-# Cookbook:: nfs
-# Recipe:: server
-#
-# Copyright:: 2010, OpenStreetMap Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-package "nfs-kernel-server"
-
-service "rpcbind" do
- action [:enable, :start]
-end
-
-service "nfs-server" do
- action [:enable, :start]
-end
-
-exports = {}
-
-search(:node, "*:*") do |client|
- next unless client[:nfs]
-
- client[:nfs].each_value do |mount|
- next unless mount[:host] == node[:hostname]
-
- client.ipaddresses do |address|
- exports[mount[:path]] ||= {}
-
- exports[mount[:path]][address] = if mount[:readonly]
- "ro"
- else
- "rw"
- end
- end
- end
-end
-
-execute "exportfs" do
- action :nothing
- command "/usr/sbin/exportfs -ra"
-end
-
-template "/etc/exports" do
- source "exports.erb"
- owner "root"
- group "root"
- mode "644"
- variables :exports => exports
- notifies :run, "execute[exportfs]"
-end
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-<% @exports.sort.each do |directory,clients| -%>
-<% clients.sort.each do |address,options| -%>
-<%= directory -%> -sync,subtree_check,<%= options %> <%= address %>
-<% end -%>
-<% end -%>
-/store/planet -sync,subtree_check,rw 10.0.48.50 10.0.48.5
default[:nginx][:cache][:proxy][:keys_zone] = "proxy_cache_zone:128M"
default[:nginx][:cache][:proxy][:inactive] = "45d"
default[:nginx][:cache][:proxy][:max_size] = "16384M"
-
-# Enable nginx repository
-default[:apt][:sources] = node[:apt][:sources] | ["nginx"]
version "1.0.0"
supports "ubuntu"
depends "apt"
-depends "munin"
depends "networking"
depends "prometheus"
depends "ssl"
+depends "systemd"
# limitations under the License.
#
-include_recipe "apt"
-include_recipe "munin"
+include_recipe "apt::nginx"
include_recipe "prometheus"
include_recipe "ssl"
subscribes :restart, "template[/etc/nginx/nginx.conf]"
end
-munin_plugin_conf "nginx" do
- template "munin.erb"
-end
-
-package "libwww-perl"
-
-munin_plugin "nginx_request"
-munin_plugin "nginx_status"
-
prometheus_exporter "nginx" do
port 9113
options "--nginx.scrape-uri=http://localhost:8050/nginx_status"
end
-
-template "/usr/local/bin/nginx-old-cache-cleanup" do
- source "nginx-old-cache-cleanup.erb"
- owner "root"
- group "root"
- mode "755"
-end
-
-cron_d "nginx-old-cache-cleanup" do
- minute "15"
- hour "23"
- user "www-data"
- command "/usr/bin/timeout 6h /usr/local/bin/nginx-old-cache-cleanup"
-end
+++ /dev/null
-[nginx*]
- env.url http://localhost:8050/nginx_status
+++ /dev/null
-#!/bin/bash
-set -e
-/usr/bin/renice -n 19 $$ >/dev/null
-/usr/bin/ionice -c 3 -p $$ >/dev/null
-[[ -d "/var/cache/nginx/fastcgi-cache" ]] && /usr/bin/find /var/cache/nginx/fastcgi-cache/?/??/ -maxdepth 1 -type f -delete 2>/dev/null || /bin/true
-[[ -d "/var/cache/nginx/fastcgi-cache" ]] && /usr/bin/find /var/cache/nginx/fastcgi-cache/ -maxdepth 2 -mindepth 2 -type d -wholename '*/?/??' -delete
-[[ -d "/var/cache/nginx/fastcgi-cache" ]] && /usr/bin/find /var/cache/nginx/fastcgi-cache/ -maxdepth 1 -mindepth 1 -type d -wholename '*/?' -delete
-[[ -d "/var/cache/nginx/proxy-cache" ]] && /usr/bin/find /var/cache/nginx/proxy-cache/?/??/ -maxdepth 1 -type f -delete 2>/dev/null || /bin/true
-[[ -d "/var/cache/nginx/proxy-cache" ]] && /usr/bin/find /var/cache/nginx/proxy-cache/ -maxdepth 2 -mindepth 2 -type d -wholename '*/?/??' -delete
-[[ -d "/var/cache/nginx/proxy-cache" ]] && /usr/bin/find /var/cache/nginx/proxy-cache/ -maxdepth 1 -mindepth 1 -type d -wholename '*/?' -delete
proxy_cache_path <%= node['nginx']['cache']['proxy']['directory'] %> levels=2:2:2 use_temp_path=off keys_zone=<%= node['nginx']['cache']['proxy']['keys_zone'] %> inactive=<%= node['nginx']['cache']['proxy']['inactive'] %> max_size=<%= node['nginx']['cache']['proxy']['max_size'] %>;
<% end -%>
- # Internal site for munin monitoring
+ # Internal site for stats monitoring
server {
listen 127.0.0.1:8050;
server_name localhost;
version "1.0.0"
supports "ubuntu"
+depends "apt"
# limitations under the License.
#
+include_recipe "apt::nodesource"
+include_recipe "apt::yarn"
+
package %w[
nodejs
- npm
+ yarn
g++
make
]
# Nominatim Cookbook
This cookbook installs and configures the Nominatim geocoding service.
-
-It contains three recipes:
-* default: sets up a complete Nominatim installation including postgres backend
- and apache frontend
-* master: defines additional attributes for running the server as DB master
-* slave: defines additional attributes for running the server as DB slave
default[:nominatim][:state] = "off" # or: standalone, master, slave
default[:nominatim][:dbadmins] = []
-default[:nominatim][:dbcluster] = "12/main"
+default[:nominatim][:dbcluster] = "14/main"
default[:nominatim][:dbname] = "nominatim"
default[:nominatim][:tablespaces] = []
-default[:nominatim][:postgis] = "2.5"
+default[:nominatim][:postgis] = "3"
default[:nominatim][:logdir] = "/var/log/nominatim"
default[:nominatim][:repository] = "https://git.openstreetmap.org/public/nominatim.git"
-default[:nominatim][:revision] = "master"
+default[:nominatim][:revision] = "deploy"
default[:nominatim][:enable_backup] = false
default[:nominatim][:enable_git_updates] = true
+default[:nominatim][:enable_qa_tiles] = false
default[:nominatim][:ui_repository] = "https://git.openstreetmap.org/public/nominatim-ui.git"
default[:nominatim][:ui_revision] = "master"
+default[:nominatim][:qa_repository] = "https://github.com/osm-search/Nominatim-Data-Analyser"
+default[:nominatim][:qa_revision] = "main"
+default[:nominatim][:api_flavour] = "php"
+default[:nominatim][:api_workers] = 10
+default[:nominatim][:api_pool_size] = 10
+default[:nominatim][:api_query_timeout] = 5
+default[:nominatim][:api_request_timeout] = 20
default[:nominatim][:fpm_pools] = {
"nominatim.openstreetmap.org" => {
}
}
+default[:nominatim][:config] = {
+ :tokenizer => "icu",
+ :forward_dependencies => "no"
+}
+
default[:nominatim][:redirects] = {}
default[:postgresql][:versions] |= [node[:nominatim][:dbcluster].split("/").first]
+default[:postgresql][:monitor_database] = "nominatim"
default[:accounts][:users][:nominatim][:status] = :role
--- /dev/null
+<html>
+<head>
+<title>Access blocked</title>
+</head>
+<body>
+<h1>Access blocked</h1>
+
+<p>You have been blocked because you have violated the
+<a href="https://operations.osmfoundation.org/policies/nominatim/">usage policy</a>
+of OSM's Nominatim geocoding service. Please be aware that OSM's resources are
+limited and shared between many users. The usage policy is there to ensure that
+the service remains usable for everybody.</p>
+
+<p>Please review the terms and make sure that your
+software adheres to the terms. You should in particular verify that you have set a
+<b>custom HTTP referrer or HTTP user agent</b> that identifies your application, and
+that you are not overusing the service with massive bulk requests.</p>
+
+<p>If you feel that this block is unjustified or remains after you have adopted
+your usage, you may contact the Nominatim system administrator at
+nominatim@openstreetmap.org to have this block lifted.</p>
+</body>
+</head>
--- /dev/null
+<html>
+<head>
+<title>Bandwidth limit exceeded</title>
+</head>
+<body>
+<h1>Bandwidth limit exceeded</h1>
+
+<p>You have been temporarily blocked because you have been overusing OSM's geocoding service or because you have not provided sufficient identification of your application. This block will be automatically lifted after a while. Please take the time and adapt your scripts to reduce the number of requests and make sure that you send a valid UserAgent or Referer.</p>
+
+<p>For more information, consult the <a href="https://operations.osmfoundation.org/policies/nominatim/">usage policy</a> for the OSM Nominatim server.</p>
+</body>
+</html>
--- /dev/null
+<?xml version="1.0"?>
+ <!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
+ <cross-domain-policy>
+ <allow-access-from domain="*" />
+ </cross-domain-policy>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
+ xmlns:moz="http://www.mozilla.org/2006/browser/search/">
+ <ShortName>Nominatim</ShortName>
+ <LongName>Nominatim OSM Search</LongName>
+ <Description>Search for a place in OpenStreetMap Nominatim</Description>
+ <InputEncoding>UTF-8</InputEncoding>
+ <OutputEncoding>UTF-8</OutputEncoding>
+ <Url type="text/html" method="get" template="https://nominatim.openstreetmap.org/ui/search.html">
+ <Param name="q" value="{searchTerms}"/>
+ </Url>
+ <Query role="example" searchTerms="Reigate" />
+ <Developer>Sarah Hoffmann</Developer>
+ <AdultContent>false</AdultContent>
+ <Attribution>Data &copy; OpenStreetMap contributors. ODbL, http://www.osm.org/copyright.</Attribution>
+</OpenSearchDescription>
+
--- /dev/null
+User-agent: ia_archiver
+Allow: /
+
+User-agent: *
+Disallow: /search.php
+Disallow: /search
+Disallow: /details.php
+Disallow: /details
+Disallow: /reverse.php
+Disallow: /reverse
+Disallow: /hierarchy
+Disallow: /hierarchy.php
+Disallow: /lookup
+Disallow: /lookup.php
--- /dev/null
+{"data_format":1,"data_url":"https://nominatim.openstreetmap.org/taginfo.json","project":{"name":"Nominatim","description":"OSM search engine.","project_url":"https://nominatim.openstreetmap.org","doc_url":"https://nominatim.org/release-docs/develop/","contact_name":"Sarah Hoffmann","contact_email":"lonvia@denofr.de"},"tags":[{"key":"historic","description":"POI/feature in the search database (except for values: yes, no)."},{"key":"military","description":"POI/feature in the search database (except for values: yes, no)."},{"key":"man_made","description":"POI/feature in the search database"},{"key":"landuse","description":"POI/feature in the search database"},{"key":"place","description":"POI/feature in the search database"},{"key":"highway","description":"POI/feature in the search database (except for values: no, turning_circle, mini_roundabout, noexit, crossing, give_way, stop)."},{"key":"waterway","description":"POI/feature in the search database (except for values: riverbank)."},{"key":"natural","description":"POI/feature in the search database (except for values: yes, no, coastline)."},{"key":"mountain_pass","description":"POI/feature in the search database (except for values: no)."},{"key":"healthcare","description":"POI/feature in the search database"},{"key":"club","description":"POI/feature in the search database (except for values: no)."},{"key":"bridge","description":"POI/feature in the search database (except for values: no)."},{"key":"leisure","description":"POI/feature in the search database (except for values: no)."},{"key":"emergency","description":"POI/feature in the search database (except for values: yes, no, fire_hydrant)."},{"key":"building","description":"POI/feature in the search database (except for values: no)."},{"key":"office","description":"POI/feature in the search database (except for values: no)."},{"key":"aeroway","description":"POI/feature in the search database (except for values: no)."},{"key":"railway","description":"POI/feature in the search database (except for values: level_crossing, no, rail, switch, abandoned, signal, buffer_stop, razed)."},{"key":"craft","description":"POI/feature in the search database (except for values: no)."},{"key":"junction","description":"POI/feature in the search database"},{"key":"tunnel","description":"POI/feature in the search database (except for values: no)."},{"key":"shop","description":"POI/feature in the search database (except for values: no)."},{"key":"tourism","description":"POI/feature in the search database (except for values: yes, no)."},{"key":"amenity","description":"POI/feature in the search database (except for values: no, parking_space, parking_entrance)."},{"key":"boundary","description":"POI/feature in the search database (except for values: place, land_area)."},{"key":"aerialway","description":"POI/feature in the search database (except for values: pylon, no)."},{"key":"int_ref","description":"Searchable name of the place."},{"key":"loc_name","description":"Searchable name of the place."},{"key":"pcode","description":"Searchable name of the place."},{"key":"addr:housename","description":"Searchable name of the place."},{"key":"old_name","description":"Searchable name of the place."},{"key":"name","description":"Searchable name of the place."},{"key":"short_name","description":"Searchable name of the place."},{"key":"brand","description":"Searchable name of the place."},{"key":"ref","description":"Searchable name of the place."},{"key":"reg_ref","description":"Searchable name of the place."},{"key":"reg_name","description":"Searchable name of the place."},{"key":"old_ref","description":"Searchable name of the place."},{"key":"loc_ref","description":"Searchable name of the place."},{"key":"iata","description":"Searchable name of the place."},{"key":"ISO3166-2","description":"Searchable name of the place."},{"key":"nat_name","description":"Searchable name of the place."},{"key":"alt_name","description":"Searchable name of the place."},{"key":"official_name","description":"Searchable name of the place."},{"key":"icao","description":"Searchable name of the place."},{"key":"nat_ref","description":"Searchable name of the place."},{"key":"int_name","description":"Searchable name of the place."},{"key":"place_name","description":"Searchable name of the place."},{"key":"tiger:zip_right","description":"Used to determine the address of a place."},{"key":"tiger:county","description":"Used to determine the address of a place."},{"key":"addr:country_code","description":"Used to determine the address of a place."},{"key":"postal_code","description":"Used to determine the address of a place."},{"key":"addr:housenumber","description":"Used to determine the address of a place."},{"key":"is_in","description":"Used to determine the address of a place."},{"key":"addr","description":"Used to determine the address of a place."},{"key":"is_in:country_code","description":"Used to determine the address of a place."},{"key":"is_in:country","description":"Used to determine the address of a place."},{"key":"postcode","description":"Used to determine the address of a place."},{"key":"addr:country","description":"Used to determine the address of a place."},{"key":"addr:streetnumber","description":"Used to determine the address of a place."},{"key":"addr:postcode","description":"Used to determine the address of a place."},{"key":"tiger:zip_left","description":"Used to determine the address of a place."},{"key":"addr:conscriptionnumber","description":"Used to determine the address of a place."},{"key":"country_code","description":"Used to determine the address of a place."},{"key":"ISO3166-1","description":"Used to determine the address of a place."},{"key":"addr:interpolation","description":"Used to determine the address of a place."}]}
depends "accounts"
depends "fail2ban"
depends "git"
-depends "munin"
depends "nginx"
depends "php"
depends "postgresql"
+depends "prometheus"
depends "python"
depends "systemd"
#
include_recipe "accounts"
-include_recipe "munin"
-include_recipe "php::fpm"
+include_recipe "prometheus"
+
+if node[:nominatim][:api_flavour] == "php"
+ include_recipe "php::fpm"
+end
basedir = data_bag_item("accounts", "nominatim")["home"]
email_errors = data_bag_item("accounts", "lonvia")["email"]
recursive true
end
+## Log directory setup
+
directory node[:nominatim][:logdir] do
owner "nominatim"
group "nominatim"
mode "664"
end
-# exception granted for a limited time so that they can set up their own server
-firewall_rule "increase-limits-gnome-proxy" do
- action :accept
- family "inet"
- source "net:8.43.85.23"
- dest "fw"
- proto "tcp:syn"
- dest_ports "https"
- rate_limit "s:10/sec:30"
-end
-
## Postgresql
include_recipe "postgresql"
only_if { node[:nominatim][:state] != "slave" }
end
-postgresql_munin "nominatim" do
- cluster node[:nominatim][:dbcluster]
- database node[:nominatim][:dbname]
-end
-
directory "#{basedir}/tablespaces" do
owner "postgres"
group "postgres"
end
end
-if node[:nominatim][:state] == "master"
- postgresql_user "replication" do
- cluster node[:nominatim][:dbcluster]
- password data_bag_item("nominatim", "passwords")["replication"]
- replication true
- end
-
- directory node[:rsyncd][:modules][:archive][:path] do
- owner "postgres"
- group "postgres"
- mode "700"
- end
-
- template "/usr/local/bin/clean-db-nominatim" do
- source "clean-db-nominatim.erb"
- owner "root"
- group "root"
- mode "755"
- variables :archive_dir => node[:rsyncd][:modules][:archive][:path],
- :update_stop_file => "#{basedir}/status/updates_disabled",
- :streaming_clients => search(:node, "nominatim_state:slave").map { |slave| slave[:fqdn] }.join(" ")
- end
-end
-
## Nominatim backend
include_recipe "git"
+include_recipe "python"
+
+python_directory = "#{basedir}/venv"
package %w[
build-essential
libboost-filesystem-dev
libexpat1-dev
zlib1g-dev
- libxml2-dev
libbz2-dev
libpq-dev
- libgeos++-dev
libproj-dev
+ liblua5.3-dev
+ libluajit-5.1-dev
+ libicu-dev
+ nlohmann-json3-dev
+ lua5.3
python3-pyosmium
- pyosmium
python3-psycopg2
python3-dotenv
python3-psutil
python3-jinja2
python3-icu
- php-pgsql
- php-intl
- php-symfony-dotenv
+ python3-datrie
+ python3-yaml
+ python3-sqlalchemy-ext
+ python3-geoalchemy2
+ python3-asyncpg
+ python3-dev
+ pkg-config
+ ruby
+ ruby-file-tail
+ ruby-pg
+ ruby-webrick
]
-source_directory = "#{basedir}/nominatim"
-build_directory = "#{basedir}/bin"
+if node[:nominatim][:api_flavour] == "php"
+ package %w[
+ php-pgsql
+ php-intl
+ ]
+elsif node[:nominatim][:api_flavour] == "python"
+
+ python_virtualenv python_directory do
+ interpreter "/usr/bin/python3"
+ end
+
+ python_package "SQLAlchemy" do
+ python_virtualenv python_directory
+ version "2.0.29"
+ end
+
+ python_package "PyICU" do
+ python_virtualenv python_directory
+ version "2.12"
+ end
+
+ python_package "psycopg[binary]" do
+ python_virtualenv python_directory
+ version "3.1.18"
+ end
+
+ python_package "psycopg2-binary" do
+ python_virtualenv python_directory
+ version "2.9.9"
+ end
+
+ python_package "python-dotenv" do
+ python_virtualenv python_directory
+ version "0.21.0"
+ end
+
+ python_package "pygments" do
+ python_virtualenv python_directory
+ version "2.17.2"
+ end
+
+ python_package "PyYAML" do
+ python_virtualenv python_directory
+ version "6.0.1"
+ end
+
+ python_package "falcon" do
+ python_virtualenv python_directory
+ version "3.1.3"
+ end
+
+ python_package "uvicorn" do
+ python_virtualenv python_directory
+ version "0.29.0"
+ end
+
+ python_package "gunicorn" do
+ python_virtualenv python_directory
+ version "22.0.0"
+ end
+end
+
+source_directory = "#{basedir}/src/nominatim"
+build_directory = "#{basedir}/src/build"
+project_directory = "#{basedir}/planet-project"
+bin_directory = "#{basedir}/bin"
+cfg_directory = "#{basedir}/etc"
ui_directory = "#{basedir}/ui"
+qa_bin_directory = "#{basedir}/src/Nominatim-Data-Analyser"
+qa_data_directory = "#{basedir}/qa-data"
+
+[basedir, "#{basedir}/src", cfg_directory, bin_directory, build_directory, project_directory].each do |path|
+ directory path do
+ owner "nominatim"
+ group "nominatim"
+ mode "755"
+ recursive true
+ end
+end
+
+directory "#{bin_directory}/maintenance" do
+ owner "nominatim"
+ group "nominatim"
+ mode "775"
+end
+
+if node[:nominatim][:flatnode_file]
+ directory File.dirname(node[:nominatim][:flatnode_file]) do
+ recursive true
+ end
+end
-directory build_directory do
+remote_directory "#{project_directory}/static-website" do
+ source "website"
owner "nominatim"
group "nominatim"
mode "755"
- recursive true
+ files_owner "nominatim"
+ files_group "nominatim"
+ files_mode "644"
+ purge false
end
# Normally syncing via chef is a bad idea because syncing might involve
remote_file "#{source_directory}/data/country_osm_grid.sql.gz" do
action :create_if_missing
- source "https://www.nominatim.org/data/country_grid.sql.gz"
+ source "https://nominatim.org/data/country_grid.sql.gz"
owner "nominatim"
group "nominatim"
mode "644"
user "nominatim"
cwd build_directory
command "cmake #{source_directory} && make"
+ notifies :run, "execute[install_nominatim]"
end
-template "#{source_directory}/.git/hooks/post-merge" do
- source "git-post-merge-hook.erb"
- owner "nominatim"
- group "nominatim"
- mode "755"
- variables :srcdir => source_directory,
- :builddir => build_directory,
- :dbname => node[:nominatim][:dbname]
+execute "install_nominatim" do
+ action :nothing
+ cwd build_directory
+ command "make install"
end
-template "#{build_directory}/.env" do
+# Project directory
+
+template "#{project_directory}/.env" do
source "nominatim.env.erb"
owner "nominatim"
group "nominatim"
variables :base_url => node[:nominatim][:state] == "off" ? node[:fqdn] : "nominatim.openstreetmap.org",
:dbname => node[:nominatim][:dbname],
:flatnode_file => node[:nominatim][:flatnode_file],
- :log_file => "#{node[:nominatim][:logdir]}/query.log"
+ :log_file => "#{node[:nominatim][:logdir]}/query.log",
+ :tokenizer => node[:nominatim][:config][:tokenizer],
+ :forward_dependencies => node[:nominatim][:config][:forward_dependencies],
+ :pool_size => node[:nominatim][:api_pool_size],
+ :query_timeout => node[:nominatim][:api_query_timeout],
+ :request_timeout => node[:nominatim][:api_request_timeout]
end
-git ui_directory do
- action :sync
- repository node[:nominatim][:ui_repository]
- revision node[:nominatim][:ui_revision]
- user "nominatim"
- group "nominatim"
-end
-
-template "#{ui_directory}/dist/theme/config.theme.js" do
- source "ui-config.js.erb"
+remote_file "#{project_directory}/wikimedia-importance.sql.gz" do
+ action :create_if_missing
+ source "https://nominatim.org/data/wikimedia-importance.sql.gz"
owner "nominatim"
group "nominatim"
- mode "664"
-end
-
-if node[:nominatim][:flatnode_file]
- directory File.dirname(node[:nominatim][:flatnode_file]) do
- recursive true
- end
-end
-
-template "/etc/logrotate.d/nominatim" do
- source "logrotate.nominatim.erb"
- owner "root"
- group "root"
mode "644"
end
-external_data = [
- "wikimedia-importance.sql.gz",
- "gb_postcodes.csv.gz",
- "us_postcodes.csv.gz"
-]
-
-external_data.each do |fname|
- remote_file "#{build_directory}/#{fname}" do
- action :create_if_missing
- source "https://www.nominatim.org/data/#{fname}"
+%w[gb_postcodes.csv.gz us_postcodes.csv.gz].each do |fname|
+ remote_file "#{project_directory}/#{fname}" do
+ action :create
+ source "https://nominatim.org/data/#{fname}"
owner "nominatim"
group "nominatim"
mode "644"
end
end
-if node[:nominatim][:state] == "off"
- cron_d "nominatim-backup" do
- action :delete
- end
-
- cron_d "nominatim-vacuum-db" do
- action :delete
- end
-
- cron_d "nominatim-clean-db" do
- action :delete
- end
-
- cron_d "nominatim-update-maintenance-trigger" do
- action :delete
- end
-else
- cron_d "nominatim-backup" do
- action node[:nominatim][:enable_backup] ? :create : :delete
- minute "0"
- hour "3"
- day "1"
- user "nominatim"
- command "/usr/local/bin/backup-nominatim"
- mailto email_errors
- end
-
- cron_d "nominatim-vacuum-db" do
- minute "20"
- hour "0"
- user "postgres"
- command "/usr/local/bin/vacuum-db-nominatim"
- mailto email_errors
- end
-
- cron_d "nominatim-clean-db" do
- action node[:nominatim][:state] == "master" ? :create : :delete
- minute "5"
- hour "*/4"
- user "postgres"
- command "/usr/local/bin/clean-db-nominatim"
- mailto email_errors
- end
-
- cron_d "nominatim-update-maintenance-trigger" do
- minute "18"
- hour "1"
- user "nominatim"
- command "touch #{basedir}/status/update_maintenance"
- mailto email_errors
- end
-end
-
-template "#{source_directory}/utils/nominatim-update" do
- source "updater.erb"
- user "nominatim"
- group "nominatim"
- mode "755"
- variables :bindir => build_directory,
- :srcdir => source_directory,
- :logfile => "#{node[:nominatim][:logdir]}/update.log",
- :branch => node[:nominatim][:revision],
- :update_stop_file => "#{basedir}/status/updates_disabled",
- :update_maintenance_trigger => "#{basedir}/status/update_maintenance"
-end
-
-template "/etc/init.d/nominatim-update" do
- source "updater.init.erb"
- user "nominatim"
- group "nominatim"
- mode "755"
- variables :source_directory => source_directory
-end
-
-%w[backup-nominatim vacuum-db-nominatim].each do |fname|
- template "/usr/local/bin/#{fname}" do
- source "#{fname}.erb"
- owner "root"
- group "root"
- mode "755"
- variables :db => node[:nominatim][:dbname]
- end
-end
-
-## webserver frontend
-
-directory "#{basedir}/etc" do
- owner "nominatim"
- group "adm"
- mode "775"
-end
+# Webserver + frontend
%w[user_agent referrer email generic].each do |name|
- file "#{basedir}/etc/nginx_blocked_#{name}.conf" do
+ file "#{cfg_directory}/nginx_blocked_#{name}.conf" do
action :create_if_missing
owner "nominatim"
group "adm"
end
end
-node[:nominatim][:fpm_pools].each do |name, data|
- php_fpm name do
- port data[:port]
- pm data[:pm]
- pm_max_children data[:max_children]
- pm_start_servers 20
- pm_min_spare_servers 10
- pm_max_spare_servers 20
- pm_max_requests 10000
- prometheus_port data[:prometheus_port]
+if node[:nominatim][:api_flavour] == "php"
+ node[:nominatim][:fpm_pools].each do |name, data|
+ php_fpm name do
+ port data[:port]
+ pm data[:pm]
+ pm_max_children data[:max_children]
+ pm_start_servers 20
+ pm_min_spare_servers 10
+ pm_max_spare_servers 20
+ pm_max_requests 10000
+ prometheus_port data[:prometheus_port]
+ end
+ end
+elsif node[:nominatim][:api_flavour] == "python"
+ systemd_service "nominatim" do
+ description "Nominatim running as a gunicorn application"
+ user "www-data"
+ group "www-data"
+ working_directory project_directory
+ standard_output "append:#{node[:nominatim][:logdir]}/gunicorn.log"
+ standard_error "inherit"
+ exec_start "#{python_directory}/bin/gunicorn --max-requests 200000 -b unix:/run/gunicorn-nominatim.openstreetmap.org.sock -w #{node[:nominatim][:api_workers]} -k uvicorn.workers.UvicornWorker nominatim.server.falcon.server:run_wsgi"
+ exec_reload "/bin/kill -s HUP $MAINPID"
+ environment :PYTHONPATH => "/usr/local/lib/nominatim/lib-python/"
+ kill_mode "mixed"
+ timeout_stop_sec 5
+ private_tmp true
+ requires "nominatim.socket"
+ after "network.target"
+ end
+
+ systemd_socket "nominatim" do
+ description "Gunicorn socket for Nominatim"
+ listen_stream "/run/gunicorn-nominatim.openstreetmap.org.sock"
+ socket_user "www-data"
end
end
notifies :reload, "service[nginx]"
end
-package "apache2" do
- action :remove
-end
-
include_recipe "nginx"
nginx_site "default" do
nginx_site "nominatim" do
template "nginx.erb"
- directory build_directory
+ directory project_directory
variables :pools => node[:nominatim][:fpm_pools],
:frontends => frontends,
:confdir => "#{basedir}/etc",
mode "644"
end
-munin_plugin_conf "nominatim" do
- template "munin.erb"
- variables :db => node[:nominatim][:dbname],
- :querylog => "#{node[:nominatim][:logdir]}/query.log"
+# Updates
+
+%w[nominatim-update
+ nominatim-update-source
+ nominatim-update-refresh-db
+ nominatim-update-data
+ nominatim-daily-maintenance].each do |fname|
+ template "#{bin_directory}/#{fname}" do
+ source "#{fname}.erb"
+ owner "nominatim"
+ group "nominatim"
+ mode "554"
+ variables :bindir => bin_directory,
+ :srcdir => source_directory,
+ :builddir => build_directory,
+ :projectdir => project_directory,
+ :qabindir => qa_bin_directory,
+ :qadatadir => qa_data_directory
+ end
end
-munin_plugin "nominatim_importlag" do
- target "#{source_directory}/munin/nominatim_importlag"
+systemd_service "nominatim-update" do
+ description "Update the Nominatim database"
+ exec_start "#{bin_directory}/nominatim-update"
+ restart "on-success"
+ standard_output "append:#{node[:nominatim][:logdir]}/update.log"
+ standard_error "inherit"
+ working_directory project_directory
end
-munin_plugin "nominatim_query_speed" do
- target "#{source_directory}/munin/nominatim_query_speed_querylog"
+systemd_service "nominatim-update-maintenance-trigger" do
+ description "Trigger daily maintenance tasks for Nominatim DB"
+ exec_start "ln -sf #{bin_directory}/nominatim-daily-maintenance #{bin_directory}/maintenance/"
+ user "nominatim"
end
-munin_plugin "nominatim_requests" do
- target "#{source_directory}/munin/nominatim_requests_querylog"
+systemd_timer "nominatim-update-maintenance-trigger" do
+ action node[:nominatim][:state] != "off" ? :create : :delete
+ description "Schedule daily maintenance tasks for Nominatim DB"
+ on_calendar "*-*-* 02:03:00 UTC"
end
-directory "#{basedir}/status" do
+service "nominatim-update-maintenance-trigger" do
+ action node[:nominatim][:state] != "off" ? :enable : :disable
+end
+
+# Nominatim UI
+
+git ui_directory do
+ action :sync
+ repository node[:nominatim][:ui_repository]
+ revision node[:nominatim][:ui_revision]
+ user "nominatim"
+ group "nominatim"
+end
+
+template "#{ui_directory}/dist/theme/config.theme.js" do
+ source "ui-config.js.erb"
owner "nominatim"
- group "postgres"
- mode "775"
+ group "nominatim"
+ mode "664"
+end
+
+# Nominatim QA
+
+if node[:nominatim][:enable_qa_tiles]
+ package "python3-geojson"
+
+ git qa_bin_directory do
+ repository node[:nominatim][:qa_repository]
+ revision node[:nominatim][:qa_revision]
+ enable_submodules true
+ user "nominatim"
+ group "nominatim"
+ notifies :run, "execute[compile_qa]"
+ end
+
+ execute "compile_qa" do
+ action :nothing
+ user "nominatim"
+ cwd "#{qa_bin_directory}/clustering-vt"
+ command "make"
+ end
+
+ directory qa_data_directory do
+ owner "nominatim"
+ group "nominatim"
+ mode "755"
+ recursive true
+ end
+
+ template "#{qa_bin_directory}/analyser/config/config.yaml" do
+ source "qa_config.erb"
+ owner "nominatim"
+ group "nominatim"
+ mode "755"
+ variables :outputdir => "#{qa_data_directory}/new"
+ end
+
+ ssl_certificate "qa-tile.nominatim.openstreetmap.org" do
+ domains ["qa-tile.nominatim.openstreetmap.org"]
+ notifies :reload, "service[nginx]"
+ end
+
+ nginx_site "qa-tiles.nominatim" do
+ template "nginx-qa-tiles.erb"
+ directory build_directory
+ variables :qa_data_directory => qa_data_directory
+ end
+
+end
+
+# Replication
+
+cron_d "nominatim-clean-db" do
+ action node[:nominatim][:state] == "master" ? :create : :delete
+ minute "5"
+ hour "*/4"
+ user "postgres"
+ command "#{bin_directory}/clean-db-nominatim"
+ mailto email_errors
+end
+
+if node[:nominatim][:state] == "master"
+ postgresql_user "replication" do
+ cluster node[:nominatim][:dbcluster]
+ password data_bag_item("nominatim", "passwords")["replication"]
+ replication true
+ end
+
+ directory node[:rsyncd][:modules][:archive][:path] do
+ owner "postgres"
+ group "postgres"
+ mode "700"
+ end
+
+ template "#{bin_directory}/clean-db-nominatim" do
+ source "clean-db-nominatim.erb"
+ owner "nominatim"
+ group "nominatim"
+ mode "755"
+ variables :archive_dir => node[:rsyncd][:modules][:archive][:path],
+ :update_stop_file => "#{basedir}/status/updates_disabled",
+ :streaming_clients => search(:node, "nominatim_state:slave").map { |slave| slave[:fqdn] }.join(" ")
+ end
+end
+
+# Maintenance
+
+cron_d "nominatim-backup" do
+ action (node[:nominatim][:enable_backup] && node[:nominatim][:state] != "off") ? :create : :delete
+ minute "0"
+ hour "3"
+ day "1"
+ user "nominatim"
+ command "#{bin_directory}/backup-nominatim"
+ mailto email_errors
+end
+
+cron_d "nominatim-vacuum-db" do
+ action node[:nominatim][:state] != "off" ? :create : :delete
+ minute "20"
+ hour "0"
+ user "postgres"
+ command "#{bin_directory}/vacuum-db-nominatim"
+ mailto email_errors
+end
+
+%w[backup-nominatim vacuum-db-nominatim].each do |fname|
+ template "#{bin_directory}/#{fname}" do
+ source "#{fname}.erb"
+ owner "nominatim"
+ group "nominatim"
+ mode "755"
+ variables :db => node[:nominatim][:dbname]
+ end
+end
+
+# Logging
+
+template "/etc/logrotate.d/nominatim" do
+ source "logrotate.nominatim.erb"
+ owner "root"
+ group "root"
+ mode "644"
+end
+
+# Monitoring
+prometheus_exporter "nominatim" do
+ port 8082
+ user "www-data"
+ restrict_address_families "AF_UNIX"
+ options [
+ "--nominatim.query-log=#{node[:nominatim][:logdir]}/query.log",
+ "--nominatim.database-name=#{node[:nominatim][:dbname]}"
+ ]
end
include_recipe "fail2ban"
+++ /dev/null
-#!/bin/bash
-
-# DO NOT EDIT - This file is being maintained by Chef
-
-cd <%= @srcdir %>
-
-git submodule update
-
-cd <%= @builddir %>
-
-cmake <%= @srcdir %> &&
-make
-
-psql -d <%= @dbname %> -c "SELECT version();" >/dev/null 2>&1
-if [[ "$?" == "0" ]]; then
- ./nominatim admin --migrate
- ./nominatim refresh --functions --address-levels --website
-fi
+++ /dev/null
-LOGFILE='<%= node[:nominatim][:logdir] %>/restricted_ips.log'
-# space-separated list of IPs that are never banned
-WHITELIST = ''
-# space-separated list of IPs manually blocked
-BLACKLIST = ''
-# user-agents that should be blocked from bulk mode
-# (matched with startswith)
-UA_BLOCKLIST = ()
-
-# time before a automatically blocked IP is allowed back
-BLOCKCOOLOFF_PERIOD='1 hour'
-# quiet time before an IP is released from the bulk pool
-BULKCOOLOFF_PERIOD='15 min'
-
-BULKLONG_LIMIT=8000
-BULKSHORT_LIMIT=2000
-BLOCK_UPPER=19000
-BLOCK_LOWER=4000
-BLOCK_LOADFAC=380
-BULK_LOADFAC=160
-BULK_LOWER=1500
-MAX_BULK_IPS=85
-
compress
delaycompress
notifempty
- create 640 nginx adm
+ create 640 www-data adm
sharedscripts
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
compress
delaycompress
notifempty
- create 640 root adm
+ create 640 www-data adm
sharedscripts
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
compress
delaycompress
notifempty
+<% if node[:nominatim][:api_flavour] == "python" %>
+ postrotate
+ systemctl reload nominatim.service
+ endscript
+<% end -%>
create 640 www-data adm
}
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-[nominatim_*]
-user www-data
-env.PGDATABASE <%= @db %>
-env.PGUSER www-data
-env.NOMINATIM_QUERYLOG <%= @querylog %>
--- /dev/null
+server {
+ listen 80;
+ listen [::]:80;
+
+ listen 443 ssl http2;
+ listen [::]:443 ssl http2;
+
+ ssl_certificate /etc/ssl/certs/qa-tile.nominatim.openstreetmap.org.pem;
+ ssl_certificate_key /etc/ssl/private/qa-tile.nominatim.openstreetmap.org.key;
+
+ server_name qa-tile.nominatim.openstreetmap.org;
+
+ root <%= @qa_data_directory %>/current;
+
+ access_log <%= node[:nominatim][:logdir] %>/qa-tile.nominatim.openstreetmap.org-access.log combined;
+ error_log <%= node[:nominatim][:logdir] %>/qa-tile.nominatim.openstreetmap.org-error.log;
+
+ rewrite ^/\.well-known/acme-challenge/(.*)$ http://acme.openstreetmap.org/.well-known/acme-challenge/$1 permanent;
+
+ location / {
+ add_header Access-Control-Allow-Origin "*" always;
+ }
+}
upstream nominatim_service {
- server unix:/run/php/nominatim.openstreetmap.org.sock;
+<% if node[:nominatim][:api_flavour] == "php" %>
+ server unix:/run/php/php-nominatim.openstreetmap.org-fpm.sock fail_timeout=0;
+<% elsif node[:nominatim][:api_flavour] == "python" %>
+ server unix:/run/gunicorn-nominatim.openstreetmap.org.sock fail_timeout=0;
+<% end -%>
}
map $uri $nominatim_script_name {
- ~^(.+?\.php) $1;
- ~^/([^/]+) $1.php;
- ^$ search.php;
+ ~^/*(.+?)\.php $1;
+ ~^/*([^/]+) $1;
+ ^$ search;
}
map $uri $nominatim_path_info {
46.235.224.148 1;
209.132.180.180 1;
209.132.180.168 1;
- 8.43.85.23 1; # gnome
+ 8.43.85.3 1; # gnome
+ 8.43.85.4 1; # gnome
+ 8.43.85.5 1; # gnome
+ 2620:52:3:1:5054:ff:fe0a:75a4 1; # gnome
+ 2620:52:3:1:5054:ff:fe0a:75a2 1; # gnome
+ 2620:52:3:1:5054:ff:fe0a:75aa 1; # gnome
}
map $missing_email$missing_referer$http_user_agent $blocked_user_agent {
server {
# IPv4
- listen 443 ssl deferred backlog=16384 reuseport http2 default_server;
+ listen 443 ssl http2 default_server;
# IPv6
- listen [::]:443 ssl deferred backlog=16384 reuseport http2 default_server;
+ listen [::]:443 ssl http2 default_server;
server_name localhost;
ssl_certificate /etc/ssl/certs/<%= node[:fqdn] %>.pem;
ssl_certificate_key /etc/ssl/private/<%= node[:fqdn] %>.key;
- root <%= @directory %>/website;
- index search.php;
+ root <%= @directory %>/static-website;
+ index /search;
access_log <%= node[:nominatim][:logdir] %>/nominatim.openstreetmap.org-access.log combined;
error_log <%= node[:nominatim][:logdir] %>/nominatim.openstreetmap.org-error.log;
index search.html;
}
+ location /qa-data/ {
+ add_header Access-Control-Allow-Origin "*" always;
+ }
+
+ location ~* ^/(search|reverse)(\.php)?/ {
+ error_page 404 /404-old-search-syntax.html;
+ return 404;
+ }
+
location @php {
+ if ($forward_to_ui) {
+ rewrite ^(/[^/]*) https://$host/ui$1.html redirect;
+ }
if ($blocked_user_agent ~ ^2$)
{ return 403; }
if ($blocked_referrer)
{ return 403; }
if ($blocked_email)
{ return 403; }
+ if ($args ~* "q=[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+[ &]")
+ { return 418; }
include <%= @confdir %>/nginx_blocked_generic.conf;
limit_req zone=www burst=10;
limit_req zone=tarpit burst=5;
limit_req zone=reverse burst=5;
limit_req_status 429;
+<% if node[:nominatim][:api_flavour] == "php" %>
fastcgi_pass nominatim_service;
include fastcgi_params;
fastcgi_param QUERY_STRING $args;
fastcgi_param PATH_INFO "$nominatim_path_info";
- fastcgi_param SCRIPT_FILENAME "$document_root/$nominatim_script_name";
- if ($forward_to_ui) {
- rewrite ^(/[^/]*) https://$host/ui$1.html redirect;
+ fastcgi_param SCRIPT_FILENAME "<%= @directory %>/website/$nominatim_script_name";
+<% elsif node[:nominatim][:api_flavour] == "python" %>
+
+ if ($request_method = 'OPTIONS') {
+ add_header 'Content-Type' 'text/plain; charset=UTF-8';
+ add_header 'Content-Length' 0;
+ add_header Access-Control-Allow-Origin "*";
+ add_header Access-Control-Allow-Methods 'GET,OPTIONS';
+ add_header Access-Control-Allow-Headers $http_access_control_request_headers;
+ return 204;
}
+
+ proxy_set_header Host $http_host;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_redirect off;
+ proxy_pass http://nominatim_service;
+<% end -%>
}
+<% if node[:nominatim][:api_flavour] == "php" %>
location ~* \.php$ {
if ($blocked_user_agent ~ ^2$)
{ return 403; }
limit_req_status 429;
fastcgi_pass nominatim_service;
include fastcgi_params;
- fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ fastcgi_param SCRIPT_FILENAME <%= @directory %>/website/$fastcgi_script_name;
if ($forward_to_ui) {
rewrite (.*).php https://$host/ui$1.html redirect;
}
}
+<% end -%>
}
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+nominatim refresh --postcodes --word-tokens --threads 4 -v
+
+<% if node[:nominatim][:enable_qa_tiles] -%>
+pushd <%= @qabindir %>
+if python3 cli.py --execute-all; then
+ rm -rf "<%= @qadatadir %>/old"
+ if [ -d "<%= @qadatadir %>/current" ]; then
+ mv "<%= @qadatadir %>/current" "<%= @qadatadir %>/old"
+ fi
+ mv "<%= @qadatadir %>/new" "<%= @qadatadir %>/current"
+fi
+popd
+<% end -%>
--- /dev/null
+#!/bin/bash
+
+# DO NOT EDIT - This file is being maintained by Chef
+
+date "+%c === Downloading and updating latest data from OSM"
+
+cd <%= @projectdir %>
+
+# First execute any maintenance task that may be there.
+
+for task in `find <%= @bindir %>/maintenance -type f,l`; do
+ date "+%c === Running maintenance task ${task}"
+ . ${task}
+ rm ${task}
+done
+
+# Then catch up with the database.
+
+num_cpus=`cat /proc/cpuinfo | grep -c processor`
+num_cpus=$((num_cpus - 2))
+current_load=`cat /proc/loadavg | cut -f 2 -d ' ' | sed 's:\..*::'`
+
+if [[ $current_load -lt $num_cpus ]]
+then
+ INST=4
+else
+ INST=2
+fi
+
+nominatim replication --catch-up --threads $INST
--- /dev/null
+#!/bin/bash -e
+
+# DO NOT EDIT - This file is being maintained by Chef
+
+date "+%c === Refresh database after software updates"
+
+cd <%= @projectdir %>
+
+# Run the migrations from the nominatim version in the build directory,
+# so they can execute while the frontend doesn't have the new code yet.
+<%= @builddir %>/nominatim admin --migrate
+<%= @builddir %>/nominatim refresh --functions --address-levels --website
--- /dev/null
+#!/bin/bash -e
+
+# DO NOT EDIT - This file is being maintained by Chef
+
+# Note: the script must return 0 only when new updates have been applied.
+
+date "+%c === Checking for new versions of Nominatim"
+
+cd <%= @srcdir %>
+
+git fetch origin
+git fetch origin -tf
+
+if git diff --exit-code <%= node[:nominatim][:revision] %> >/dev/null; then
+ # signal that there are no new updates
+ exit 99
+fi
+
+git checkout --detach <%= node[:nominatim][:revision] %>
+git submodule update
+
+cd <%= @builddir %>
+cmake .
+make
--- /dev/null
+#!/bin/bash
+
+# DO NOT EDIT - This file is being maintained by Chef
+
+date "+%c === Starting Nominatim update cycle"
+
+starttime=`date +%s`
+
+<% if node[:nominatim][:enable_git_updates] -%>
+if /sbin/runuser -u nominatim -- <%= @bindir %>/nominatim-update-source; then
+
+ if ! /sbin/runuser -u nominatim -- <%= @bindir %>/nominatim-update-refresh-db; then
+ date "+%c === Database refresh failed. Stopping updates."
+ exit 1
+ fi
+
+ pushd <%= @builddir %>
+ make install
+
+<% if node[:nominatim][:api_flavour] == "python" -%>
+ systemctl reload nominatim
+<% end -%>
+fi
+<% end -%>
+
+if ! /sbin/runuser -u nominatim -- <%= @bindir %>/nominatim-update-data; then
+ date "+%c === Data update failed. Stopping updates."
+ exit 1
+fi
+
+date "+%c === Nominatim update cycle finished"
+
+# sleep a bit if updates take less than a minute
+endtime=`date +%s`
+elapsed=$((endtime - starttime))
+if [[ $elapsed -lt 60 ]]; then
+ sleepy=$((60 - $elapsed))
+ date "+%c === Sleeping for ${sleepy}s..."
+ sleep $sleepy
+fi
# DO NOT EDIT - This file is being maintained by Chef
NOMINATIM_DATABASE_DSN="pgsql:dbname=<%= @dbname %>"
-NOMINATIM_MAPICON_URL="https://<%= @base_url %>/ui/mapicons/"
+NOMINATIM_MAPICON_URL="https://<%= @base_url %>/ui/mapicons"
<% if @flatnode_file -%>
NOMINATIM_FLATNODE_FILE="<%= @flatnode_file %>"
<% end -%>
+NOMINATIM_SERVE_LEGACY_URLS=yes
+NOMINATIM_API_POOL_SIZE=<%= @pool_size %>
+NOMINATIM_QUERY_TIMEOUT=<%= @query_timeout %>
+NOMINATIM_REQUEST_TIMEOUT=<%= @request_timeout %>
+
NOMINATIM_IMPORT_STYLE=extratags
NOMINATIM_USE_US_TIGER_DATA=yes
-NOMINATIM_PYOSMIUM_BINARY=/usr/bin/pyosmium-get-changes
+NOMINATIM_TOKENIZER="<%= @tokenizer %>"
+NOMINATIM_UPDATE_FORWARD_DEPENDENCIES="<%= @forward_dependencies %>"
NOMINATIM_TABLESPACE_SEARCH_DATA=dsearch
NOMINATIM_TABLESPACE_SEARCH_INDEX=isearch
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+#Data source name for the database connection.
+Dsn: 'dbname=<%= node[:nominatim][:dbname] %>'
+
+#Path to the folder where rules data are stored (geojson, vector tiles, etc).
+RulesFolderPath: '<%= @outputdir %>'
+
+#Prefix path of the web URL to access the rules data (ex: https://nominatim.org/QA-data).
+WebPrefixPath: 'https://qa-tile.nominatim.openstreetmap.org'
+++ /dev/null
-#!/bin/bash -e
-
-# DO NOT EDIT - This file is being maintained by Chef
-
-# Change to Nominatim directory
-cd <%= @bindir %>
-
-num_cpus=`cat /proc/cpuinfo | grep -c processor`
-num_cpus=$((num_cpus - 2))
-
-while [ ! -f "<%= @update_stop_file %>" ]
-do
- # Send output to the log (logrotatable)
- exec >> <%= @logfile %> 2>&1
-
- current_load=`cat /proc/loadavg | cut -f 2 -d ' ' | sed 's:\..*::'`
-
- if [[ $current_load -lt $num_cpus ]]
- then
- INST=4
- else
- INST=2
- fi
-
- ./nominatim replication --once --threads $INST
-
-<% if node[:nominatim][:enable_git_updates] -%>
- pushd <%= @srcdir %>
- if git fetch origin; then
- # will trigger recompilation if necessary
- git merge origin/<%= @branch %>
- else
- echo "WARNING: git fetch failed."
- fi
- popd
-<% end -%>
-
- if [ -f "<%= @update_maintenance_trigger %>" ]; then
- rm <%= @update_maintenance_trigger %>
- ./nominatim refresh --postcodes --threads 4 -v
- fi
-done
+++ /dev/null
-#!/bin/bash
-
-# DO NOT EDIT - This file is being maintained by Chef
-
-start() {
- start-stop-daemon --start --chuid nominatim --background --make-pidfile --pidfile /var/run/nominatim-update.pid --exec <%= @source_directory %>/utils/nominatim-update
-}
-
-stop() {
- start-stop-daemon --stop --retry 3600 --pidfile /var/run/nominatim-update.pid
-}
-
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- restart)
- stop || exit $?
- start
- ;;
-esac
-
# Vaccum all tables with indices on integer arrays.
# Agressive vacuuming seems to help against index bloat.
psql -q -d <%= @db %> -c 'VACUUM ANALYSE search_name'
-
-for i in `seq 0 250`; do
- psql -q -d <%= @db %> -c "VACUUM ANALYSE search_name_${i}"
-done
-
version "0.8.2"
supports "ubuntu"
-depends "munin"
+depends "prometheus"
depends "systemd"
# See the License for the specific language governing permissions and
# limitations under the License.
-include_recipe "munin"
+include_recipe "prometheus"
package %w[
chrony
action [:enable, :start]
end
-munin_plugin "chrony"
+prometheus_exporter "chrony" do
+ port 9123
+end
# chrony occasionally marks all servers offline during a network outage.
# force online all sources during a chef run
# DO NOT EDIT - This file is being maintained by Chef
+<% if node[:lsb][:release].to_f >= 22.04 -%>
+# Include configuration files found in /etc/chrony/conf.d.
+confdir /etc/chrony/conf.d
+<% end -%>
+
# Servers
<% node[:ntp][:servers].each do |server| -%>
pool <%= server %> iburst
allow ::1/128
# Run an initial NTP sync on daemon startup
-initstepslew 30 time.cloudflare.com time.google.com <%= node[:ntp][:servers].join(" ") %>
+# Use a few IPs here to workaround DNSSEC failure if time is wrong: https://github.com/openstreetmap/operations/issues/654
+initstepslew 30 216.239.35.0 216.239.35.4 216.239.35.8 216.239.35.12 time.google.com time.cloudflare.com <%= node[:ntp][:servers].join(" ") %>
+
+<% if node[:lsb][:release].to_f >= 22.04 -%>
+# Use NTP sources found in /etc/chrony/sources.d.
+sourcedir /etc/chrony/sources.d
+<% end -%>
# This directive specify the location of the file containing ID/key pairs for
# NTP authentication.
# information.
driftfile /var/lib/chrony/chrony.drift
+<% if node[:lsb][:release].to_f >= 22.04 -%>
+# Save NTS keys and cookies.
+ntsdumpdir /var/lib/chrony
+<% end -%>
+
# Uncomment the following line to turn logging on.
#log tracking measurements statistics
default[:openssh][:port] = 22
+default[:openssh][:password_authentication] = false
firewall_rule "accept-ssh" do
action :accept
- source "net"
- dest "fw"
- proto "tcp:syn"
+ context :incoming
+ protocol :tcp
dest_ports node[:openssh][:port]
end
# DO NOT EDIT - This file is being maintained by Chef
+# Automatically generated records
+
<% @hosts.each do |host| -%>
<% host[:keys].keys.sort.each do |type| -%>
<%= host[:names].join(",") -%>,<%= host[:addresses].join(",") -%> <%= type %> <%= host[:keys][type] %>
<% end -%>
<% end -%>
+
+# Manually maintained records for Slough
+
ridley.oob.openstreetmap.org,ridley.oob,10.0.1.3 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCohCtONR/6e/RvHnLlSbvl0GqY+EJeTn+Sxu2PyWsw+W1OAfa2jmb2DQg7S54CwbkyI/owJdVrM8Gj3s5CVOi1kIddu7+pbkqrIZKo4Mf+jviFypyZoGYHnPSBwEfgAWKtfBepnbW2RIZ9+JEXLjUyOFwU6jT8QnQMKJc5FiDP3Q==
-ridley.oob.openstreetmap.org,ridley.oob,10.0.1.3 ssh-dss AAAAB3NzaC1kc3MAAACBAKzNiUprAK/uF6ippll2gTyE7QIYg8kcE1a59/4iyyh56ChG3W4bq8jgA6ZLvJRks+rbKnjs98duqFKFoGC7sXmvNvLGD7jtSbAUkiPzNUsQ1uwPatNJk/mY5zzHjaxmgOUfA0EtDxKgvxli0atn8Xj8PGy49BbtlBPdnS+tItQ/AAAAFQCO2II1Su14H1gaeU0ogUCkG20ePQAAAIEAo0+0I7Ha53KM9xJWt1qQAVTV3FTGrOwrmedpz6JYcyELhNhC/ZUDOXu5GKqkp5SRcXZ9NRV4FiDMZgKvMGyvRcF1ZOkytNGtx12FiXAzVsM55O+hszLouqZocJVXY6Km3SKmVkymGi+unoowCHWMWJEIAjz80KyR7dsXHQKqIXEAAACAdlDbeOLTQLcgwTGRMbJR63fz6zvQQMZVJ3DDYzQxiW/0qB2CeaB0CuS9DDSJBLVlp2C9MIVnDxxaQi1KmUOvNs2fqb0NEZ8AQG7clCASgf9nXN0EBju+dZ+lGcB6c5ZIcDB/z0gFEp/16sHe8bay70Zp+S4ot6jXD5UM/pLSmF4=
-urmel.oob.openstreetmap.org,urmel.oob,10.0.1.6 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC/Z50neDHObFvqY7SjrvtebendKtlfZ5KdpUHJXzootFg5zli09HaMep8YuEqBK9n1H06qnLQY6Hr3tKUEMBjjn1VS/hiB3OQlAqci0YEqcgwyiBTz2Etkb7lDXgJVDcFA5Pjj5sKnXw7gi4Nmkgg6cfQb81fed1ySGArcFY6PFQ==
-urmel.oob.openstreetmap.org,urmel.oob,10.0.1.6 ssh-rsa AAAAB3NzaC1kc3MAAACBAJr/RfX1uZxsD/wuhnTwManZnbVET7yjqGx9H9oVXgDfGNDpk22U0/7VKh0BVHi7iC6Z92YWgCG2Os/SuZgOLqXxdJAjZv9iYqBFQBszzBjGpbtpmOZPzi4q/B4KtXmsiWVPk/eQoW7JodeaalGEflJbYY4rdtfNhWl7uR79NH9lAAAAFQCGJ68LbEk6z0t0fV6UuM2C3KDODwAAAIEAilB3PdoejxgWtd5zVWfK1pYooWyplBp0/qkQ/WV1sT/4+LsuDk1ttszD4DkyvSFwgXKULdcWl56YI2+rFS9busxyNVhM8u5ou7rMvL/laNqkruK8FGdObo1CrpqNS1CuTEcZnIXJcz9grYdmwx9Vt51V0TP7ExKggijX0FmYN4YAAACAJZy0ekCJk2l2kJwTN6D7J4NLIip4Xyv7YZhOuguhEXjmowQrAqsXRyBED0cMdC4DuUOO0AmbLJ7cw/IJ9rf5d87ZVRx8EBaGLd+WAtDGoSsLnYgY9iRWpKkYqfhLAwSfXA9d5iO1rh+FWngLsCBJ3aDurJvQHCw/xVai76tnWTU=
-#zark.oob.openstreetmap.org,zark.oob,10.0.1.8 ssh-rsa
-#zark.oob.openstreetmap.org,zark.oob,10.0.1.8 ssh-dss
-eustace.oob.openstreetmap.org,eustace.oob,10.0.1.9 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC9wLWa3gAdXL/oUw67cLoHKiIOd959u++OOjXLR2OcyDkSLNTQgYkawEOcNgRVBcLjXh7ej9ktuTFbLWwR/Uvx7ftP5MH0Luo7Z9CvrQjw9Eu+G/CdGzvilHSeSAdCJYWemHXqKT9Qo9zJt2BI7wRfkFKdA5uXezwMYQtiQRHMkw==
-eustace.oob.openstreetmap.org,eustace.oob,10.0.1.9 ssh-dss AAAAB3NzaC1kc3MAAACBAMaxIrNlpW+VWMGGZ2NWdXC5Dbub7WluWXVf0kNwadZcwqn60wchAUDWnOL6grGjmYNPuHLW1P7tromy/uAssMML9YiNhCbJGUMF0IDWGl7bGjoOBsdp2slRaC9oZEceXH/yaRZJbxx9dri85WFLP9hz2A9mgi6Yx2k5oc4b2jr9AAAAFQD3k+OjolSAPwhQcYB97d5DDWjiawAAAIEAo7nRfP1i3VC3ovNAvY/SlvIq6iGorlkg8kMuBdTb5HPTPR8kOdplHGQ2+8es5H8a43GZorXbaUjsrzlQ98OzHrlw3BEzFvFZgY0kJwD64aeHOsDhltHzWV0tLz0Al5lR2ZpAE7V7Wv3x3wg3a+d9pmGkkgSwAqVQAsbPTp3wma4AAACBAJnhfhHZWrgNNnagbn+cuPpIC8vSwp/GNKK6VoQm7jq1u4t4eXPqHDuNA18pE1ngqPgZk1DYQUp98G1zKlhVJrUYHqi6wNG/qBMN8NuOyDeJ3a0iO6XIccEHvS15xzy4hpRerrg6yFeIhwZc1MbsEZqnPQzB2nJKtf5BqaeOjmcN
+snap-02.oob.openstreetmap.org,snap-02.oob,10.0.1.4 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKyiu+/H4R/Dx1dzhWIH2Z4+SHyhgo6xONxKjlC6te2blHPjbiWgZzS+WWQXj8siiv6w98p/DonTV/+tqW9RP7fJLca0UBjexQwZBGxjBWPsMCG5bdjWLtiQCN5vVD5Hy3A/6TUeHFYfbSbEuUO+VZVHR6fVMJ0sHHy9eIIwDNsyzGoi2SDB/QsuNgSK8y0TGBQzqHPv0AAGhvmvRONGO/htLZ3lsSuvZQ0D9NPx2fNbcFzkPsOUH05I+1+Wq3tnB7doJ/+hzj6/+wyPZar0zqhNs9YJrKrSOxiltVNnObwFHWvEZabHF3jKDNzmr4IHYUgEMwoMeHvXwI1ly0xz8T
eddie.oob.openstreetmap.org,eddie.oob,10.0.1.10 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+CNWzEucmDqWDAP2yq5gNGq1yC/1h5KohNb2sxOkac5RSij6/6UumO8tiW6PVY6wmiI01L+6UyRIfxWzqD/p+Pm60fNGJATrUsED/EEEbxKppWqbr5RjQfmfRqu/Msv0/QR1XnCEiEH2ixiubBBN8091Jn4m/GpZkLkcizpwOE3w3/FtUhydhdHgRKxQN8Mvu/pu9/6DocI7dNWEKWVUG8gbktUHe4+gHW9RQTPe1XISECt93i1NR3DKD2ldbtZbVeo9H0oRw1v9hmQdKXz6MUBQDenr1f1nzVmMqoLXJkdO2xBh2H9a6QME63nT+eO48BT/fo3VHomqFrR0MceGJ
-eddie.oob.openstreetmap.org,eddie.oob,10.0.1.10 ssh-dss AAAAB3NzaC1kc3MAAACBAIPneLfNaMa1qPVwRTKArXULa3ZRkKxia22DdT6ajV3HB9c0vjbMsI08vjjx9nWk2YWsZVuxx2kXi92o7uPJabFrstETbOv0TGTj6VVWThgGAqa5k7orMiSPOvyLPP3E9BOdf8nRpSPIq3cs/cBi4Oz0sPvbfljomXhgt1yC6EoRAAAAFQDqrUdtdgM33cYRUGqZ4MmZuyrHawAAAIATBEq5xAT0fH0hUJ47EBV9LRyi4kJfMyBlNwrSthUdIXhnhUTsO0se35I/1NOQhTcyI4fD+ZjR8qyy5SaR/QHFar1RKUksVa1S5JH+EaLHMSEEcdZCa7chx4Rg3UMJIHEE9zoPXn7VrbiAVtHck8IY/yIrSQpznIwuZGGonregnwAAAIBVv82Vkry8ypz8o/na00b03+n2KWRrkkWqKZvXSN43zVV6GQuwpgZpDjA6bLJjAkX27H2+jYB9QO3h/r0NndV7jkSPfHlCYgOg1HICI221Bnj2r466Fz0UdKI/wQqkJovJzNjrvwfESUqPfeTGGGo8AbyLlTI/JEUrHADmshS6LA==
-draco.oob.openstreetmap.org,draco.oob,10.0.1.11 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgHj1uavQKI1MXJaspRJasiPvhrM+EB+p47PuFh/BgFK4P5DnirS5sfApEheuGY7vcIiBnG2kcpNLiFmVylYXG1DbvBXsN0zLyJiyegdbT/SFjMq6AXyBfqFOA5na977JmJNBwzG7Z7jjeo4ZowRMSyQ3DjmGdj6vmSyT/BYO4E5Z
-sarel.oob.openstreetmap.org,sarel.oob,10.0.1.12 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCohCtONR/6e/RvHnLlSbvl0GqY+EJeTn+Sxu2PyWsw+W1OAfa2jmb2DQg7S54CwbkyI/owJdVrM8Gj3s5CVOi1kIddu7+pbkqrIZKo4Mf+jviFypyZoGYHnPSBwEfgAWKtfBepnbW2RIZ9+JEXLjUyOFwU6jT8QnQMKJc5FiDP3Q==
-sarel.oob.openstreetmap.org,sarel.oob,10.0.1.12 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgQCXV76oba/hqR50+HL1YjMeMPjBj8DfyNPcuEJwSO+TFbn4IW4xkxYYl3w4NuD8H6gj2Myk55Wza5BIR0oTWtuQuGiAKld+sIcMb7R2rT2KustEVuvy5GM1/NkAJ+sUa4lTTl64KPpFukFIC8Ma4hiEhXA4LnN02DZe0NdvyqkC9Q==
-noquiklos.oob.openstreetmap.org,noquiklos.oob,10.0.1.13 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDE5XeF6tG4hu9M0m+JWh4QJmL/52+cfeXbV4qfWwdJjSH9yBzYP9LiDM97gMXMUSnomAs7GO0KMwEdO9xuIZWeYFyHvs+1a73fAus8bcAbrZPuFfPfrW3JHKtWsfhUqYNJuRHLaimLIRyqgsXy3WAHf35v9kY1DmMWkf5/VTrp0w==
-noquiklos.oob.openstreetmap.org,noquiklos.oob,10.0.1.13 ssh-dss AAAAB3NzaC1kc3MAAACBAPK6Av/wAEtRnOx12117EtAhBPnodjQur0/k0pTAaGCZNnLY3E5SD7CvSqtB+LhRO/VSHXl1Obkh4mvR6oKEDE2XOWEG5Ofq3mWngT9Ejo0Rretzc1JU7L6WPZ8N/D+3kQUXpxDYzK9CcKz90k0msZUFRfGkHVE12ip9f7G/BWPRAAAAFQC5wUn4ZkWjt0z+/bUUOe298i0QvwAAAIEAz6dx6w5equWz3T8DWPM8LRGhE6ASrwR2UNpFe+sW5EBp/M+Zgg5Ztne1nIQaDSh1iKL0qzSGYxTIb/sIDKAxy6CzTjEhWRGmuDRTPQkXwD9iXcNaLChEEP6AryrI193LnLKRGKVve6gP2vH4tpn3Ve68HSKL4Ggz2L9ysKxJppEAAACABSHM7Ez/2oMaDGNRvgWc+ViB3QZOB1CTnDOkRZuhZXFMmTGXaWPzlwqPLZKg+wVOnJgBJ4BTUV6WovPGPYWadNuqhlsKjflFQyYSkyBA+4gvZ45TwbDE4HTQ1BGlXJVA3vq5HAqcxlo2CAj4HCQJgVHzd7sfH+WwyruGDu58ThU=
-errol.oob.openstreetmap.org,errol.oob,10.0.1.14 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEA1riMj4gWqiovniYhlFNUxMm/AGmV/C2GjcMP+NcJ1ZyP4OdytGeGfhUm5GwVwraimkFQQlfEDcUWY7OX4EG115E8i15cUt6s6Ya2E6AXydigvBbrdp8MNnPOWBifVN3/5Cgi8nrAebmPs88ZZx2KM/Df5qIB2rHYpuHYyl+MpqE=
-errol.oob.openstreetmap.org,errol.oob,10.0.1.14 ssh-dss AAAAB3NzaC1kc3MAAACBAKcnhyMz3C4sku0e1/nFailjoPcMwLazXq4H/kUsdlt+f2By73F5KdUWffxoeRNL0UVT7+VCKG6IXmXGkKVfvpTipFjkP1N+b7I4SuJcQ/EUNPTCGAfC3l691K8jUBD6WSlQUqZtKGnpDS1zI/ZIYiNqrQnWu2RTYnP3QvY7JigDAAAAFQDI6aaH6mWx7vTVS9m3tyXQ4GQ08wAAAIAQjAM+q8Hfp1h45UjTeD2jIA74asQl0M+4q+4EcnNPnKXRbEBIg4rCWkHdd06uhayXZ91KzCDcj1b2LSb2zOE4U1MDEpdVnz22PuEl/f6/epKmLOqHoOGu9/9Lud6OoZQSveEPYmcpEEpt1RCN9ZvkVtFdLwtQ8+CSSGXg8yfCxgAAAIEAjQztmG1LN/e7pNRY0MtV148rJY3mR2knJegg0yBOEWHUGtKY91lgboWie1YTGR3RiXckJFFYkOGWAxqEVM//+rW0hatCxEp/mWEt/GWKPpV52fc4BUhJbi9hb8sg+dAvfoHwUL3CzHzqapaRNxxbfest8dfvascAjRDFP7yxU9w=
yevaud.oob.openstreetmap.org,yevaud.oob,10.0.1.15 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAuWeUQd5ssUd5VFyTMXgC+U6c7s63mtuEj+cL6x8EU8PqNS12RGwLpeAI5VL8UzM0YLyPjPh/yzdQN2tl9ufK7KZF0apvoSZgp/uwyG+CgdFSf66nTrZN4NA/QP1ikH3kbqcM87LfNjCrMXnqMBJ/OCqz2z+An8t0KGDXS8haxlU=
-yevaud.oob.openstreetmap.org,yevaud.oob,10.0.1.15 ssh-dss AAAAB3NzaC1kc3MAAACBAL6RC7IMuQEtD4JIRmBJEownC0a7ZEvfCTw20PV5MjWb6twZlGBK3IA/0yV0oJ+75W6VWizn3cWSBS3y1zD8KktF4fh4+FVyin9WTyFuwME8cYmRPV+kuOa1lF1sLJxqvZJRjKMjweLeNTKnl1mb03049SL2YoGwMOTdVgVBjEyFAAAAFQC7rQIvnfLYbQdX87DwlzfMDALOoQAAAIEAmAu2kK8atEOR1Sc6maxYKSf68MYMHoTpm2MW9q2x5ls982kfEUMJ3h641cbRgOAuCmQU3gHnt73sl5LY3K3oLijIhSQm8+l+GkrXVhdwx7ScLXf+8TJZRWiP6Q98VWM4E3L4wmiJksLbTlxdoew3lv8gGhbpk0XuSyLWIBZIKJAAAACATogkqFXhPFzOMRJAR6G8J4bOqg9Ae2cGtf4aMZ9xdm/Hm7YLSu3kn5IhawwU+DL494VF+ky69T01iY3e4m/kQhYB4emlqsRHzVscblVH+GL6sVEkct0HMzfqzEFcfYWqqMdig9EwTzHwJzkAb4WqZdGnWG3Ln88x3liyDZTpGco=
-clifford.oob.openstreetmap.org,clifford.oob,10.0.1.17 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCsCrNQ+QQg2UUGhBpgjlLAF4gI48VDGmcF9prulYDxduyGJIrqhOjQtKLjNksMr8TEblmJsI4JzPf1lY1rVL3Q/aZWJD5X4Q0DgEtNzfinI9JAy77JASj1osBPU2RfWSvK9C2TnEoXHxuyGKMw9iuuPLppNMjZ103PYprQeAXi1w==
-clifford.oob.openstreetmap.org,clifford.oob,10.0.1.17 ssh-dss AAAAB3NzaC1kc3MAAACBAM+YhVzoOuKt/0UrkDpWCsDgYKPvbfuvSrLeyZfssRuRP1bVsY39yfl5avZM6YwYhzuyRAbcOLYa+9ien1QTeTbV2qNogx+/yt57DWKVv7nX6WTSVfYFAvx+CMy+L6O8N6VnKXJaCcbQxOFx74c0ysXorNYU0c8++KyNfMmVVjJ1AAAAFQDoCl23tnp1pcVbUFAAxAEUb77aAwAAAIAOpGMpxWPrd1y+IxLLLCohRMCv7JlUy324PMMwNx2/u2fF3oh4kL/EUarD4/6iU1n5PJo441bLuOj5Mb58/O8qdWYwBjbUoj1CiA7qF3TXWGmPX84AlwwLE12TIH1sTRlZTdrD6+js1KUUMSzMz8tEi4tJs+bXYf++ng12sqP48AAAAIBvm/z7yPKGdLPP9i9LzWShLJKrbY9zx0BOsIzzeVJjShdyB4+NZdxQR1jjDcqJ+r0DXtanmhS5DLOS6zGYfnzzsCNTxHM/Ne0wF4goc4LQGKg2aClmyx8ZvqwF96d8nQcUIbLUydbE32xmh0bIbzVchLKEm5PuNYf/aU4snCyDGQ==
-grindtooth.oob.openstreetmap.org,grindtooth.oob,10.0.1.19 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgDwRqYuKXX3gENA5JHkVTBEL5MxC0N5Re0uX/hAVTv7AurDlJyaN34ZdK+k89XjQBPNMn7DhwA/+ddXCWg0Bb4KEngfKys9oMhZcwEWCD8LFWJcKugATfFHJPtduJrMx5dNEfQtpA0od7Ep6XamGcJ/Hwxa5iQRlD+8Kr419qNTY
-pummelzacken.oob.openstreetmap.org,pummelzacken.oob,10.0.1.20 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDEhjC0AfmTSwq1TgcwvSUZgzGJp6fP1DXkYfgREfgX6MQX0uRBTLgWKM1Nz2tYb14mjycJLdCjSBCzuHQg10ufX3+5nzR+xKIy7cgwqkl6I5/jX7BZNK6t8XZfdmwnhAhLqYfG5FA49eyaVNdArgHu1fv7xczKjRAMOlKhh083038bCD8BYmBoKwj2J6D6fp6wHOD2UU4rvTP2nCEYsvTd6s3/yvTOB2bFhz2qaqOhdNI1w+dvcZLPUYO5hdndw1LGC6v56IbmMquxcieWuOtU+fbTMnI9teNo4CLPVEzb3kmwhl4LyJEA1Sx65Bz7Ve4wfgUInPoBfiX1gdSjAqH9
-pummelzacken.oob.openstreetmap.org,pummelzacken.oob,10.0.1.20 ssh-dss AAAAB3NzaC1kc3MAAACBAN3kGdbPfrsSjQuX+9kk/an83YUlJ+Yd4V+AYbRrMRYBJEIQQOYxFOFwMOdmGRIFyLj2ZXKuYY3/5UFXHFeWZxqY6kWJ0JybFfOJaZu3Iwgh8gLlBnfkRWAD8WbzvXYTCwg8yrM335tj550AqrQ/6R09l0jveeK4EyA2w8Afdle9AAAAFQCOclxhmRDMVD8adpeBrpXJ0q1SvwAAAIEAt+0ZFeCMnteeadmiCrVbHpMot2FRcem87KouLdNgdOxOpuizMJgSSHEXBA6IwvRAzrLInpm/DoCdW+bdnrJkq8qs4gEhM6Dg3tDAiUz419S/sV/uZZb9O1aN/MBEzfysO+hnxemQvmQiA1vymhWov5dNl78UwFzETUj9xwW4kaUAAACBAIgjeLkkakNDkSRAYYh0X5hGjExvYRerNWdZ6hQsGKGlf3Ud0sUkKrtzpYUvWFQLnqniQXs9q0hTTxa4rVWHiCU5+R6gBOk5VgoVyM+evuOKFT5a7TorE5STDII+PQFSHQ2dJR2QsVaKmNbcSxQC+k3ttC8vBEAmIOl28m+QZ9kA
-grisu.oob.openstreetmap.org,grisu.oob,10.0.33.20 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDTEivJ/aHG2g7TVGEXJUDcOrbQKMOwYEzWiKvMTsftxOKqMW2uKzCZDkW3BNXIBiAXoswaqK0qkh519i56tY9ff7XjH5YoYbPyWwbhMPoBlIc6wBF+uMV3dBRrb7iRe0HFhpl/XsTo5vw8x+5T/ITrlvI8T7ZfE6uTLxKFDxYOiQ==
-grisu.oob.openstreetmap.org,grisu.oob,10.0.33.20 ssh-dss AAAAB3NzaC1kc3MAAACBAIrAKvS58z4zmaRWwebJxgUUiy/P2+AWODjz2FcqspmkXXnSkXD/tz3djsp/PwgPUPt/y1J+H2dfDY0qnTtY4SM1DJi0848/BG/C1P0zb/3mdtJO2FdMVVcwITCX0XZg7ikFf4zZ9CJRiuAbiS6CKCIXcvxHhBx0O4EEaK5/PwLxAAAAFQC6Rg2wsfl3aKpecSD0ed9Ysekx8wAAAIAo1yE6yLCH6+4NEA2+2mz3XWXdf/nzOWzFd1XqZIqg3Jj8MzaNS1GLbm3FlVwl7qlXr60flsXggYkZxwXyLKMH9fhFnyrTZOJMKmLKmeqcDTZqItW7hwsaKvM1vd+ZysmOVkFiXKJuD+25AyTmbFpNUvBdIHYiL1jQaIxLEWnN+wAAAIAuF7tHFgLgrZ84nc3Yb003llMmiwwaSUjF2t9y81t+FJ4fOwhFO7lIapijrsm17v5OBSOgAONfgzNS39U+VlX61PwDmIobe8+Q8zGOv/9tkK79YwNsG/dXhQ3e7gZH4wcyNgO1BufEuAOYMxE454rbv6fdrhvsUlRgEvF+teJqrQ==
-spike-04.oob.openstreetmap.org,spike-04.oob,10.0.33.21 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgQCIrf3Ca5+Cyk7/QYU2krboxC/qhHwjvtzBpcAtVya4YPpkiQa4G5KrJQ8oxvLL7j1atgYs+GnErkeUp89SLLMJ1spbjMMubA//Mr56Bp/V/ZCr7uk6c67vA+P+EIb9QhqJt6eay4fFZ75dccw76GnDunD6ADf1VTzawYykyIrm8Q==
-spike-05.oob.openstreetmap.org,spike-05.oob,10.0.33.22 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgEvdV6XL4KV/RCLZFhyM6sSGOWOia22L2Ddc28mS8MdZTr8b/iYJpFUCmGREovFxNI5MXzPhDKTomiW6UKmoxhQcsS31Y70BdsMA+XcNqwktFUkFfXMaat43gJ8gL5lVDI3AomjxIfGoouFEhIzTrj0JYMNf/q02YJm7fPvAZtuv
-katla.oob.openstreetmap.org,katla.oob,10.0.33.40 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgwCIJ+bSxbMsr6wurBXYkeqoznHnJT4zrN7nHtajgs5CJLIiWO+Eq/Lp+egz6Irxwk3v+kbfKW9RUum5fOMfkWFwaQxP41Cz5RbMmu5Jsm4MQKr4PPVxbLbPk75OeVgo+nfkzBupsBuYGMp/GCpjTJ8rusPmYxzWBek4amKL5udfA9Ld
-katla.oob.openstreetmap.org,katla.oob,10.0.33.40 ssh-dss AAAAB3NzaC1kc3MAAACBAP4oHi33lAVyP8zjoRZe6kxcZGJi1JOgF1vpZqEsxA97yCaLGVjc2cdxi16namqdJ/DgQaRpGRM+chP6AgGN9FD8Z6Wfskm+2sghPpcGRUkr7u6mM7WlJ0xQehD4LDcxFEpZKxtalf6TlxXn9cO0VaL9NNVrpU34c2Pqxl7wg/QnAAAAFQCB10EQxYDOnsxN2xrSHEbmgA3K0wAAAIAWN0b4KREM6Uc6FVkRtOjkiAR8FWmCg8nNQaqlKIPlM4hsrIcPC5yZfc7BzamQSy4PpHNGZG64CkYr8tn8LGWouHVKKbeFOWEXIBsRBSf1NNaYI7cS7WPnGVOmkt6yHvWwPlDcVO8FpPUL9pA7kf6iCuQNdD/MyOBHdbVoU9LcNAAAAIEAsXBb+3EZhsRAYL9Jm22PsrsW2o/hO7aomMeEXvVGG8Wuy77lqmcIvlyW3zhHBs7ubI9TZz1XDsgLK9giCkmqCyKmUsTXGsu9e4veOq+sgvXdbhoBMVi90IFsPLPUdPN5mfovBDHkwi60VtDwOLAX368pFfBfSA50CZWfhwUu26E=
-thorn-04.oob.openstreetmap.org,thorn-04.oob,10.0.33.41 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgH5H4Ra0f4+LfMyJbVpoJIN9wPrC0bbNEJUVIOmtPpxRE4HvoqDOBE8XfHIunhNeTxK5Yzfinz+fCq2XCv/8Sgrr1qJBUQwi9kHfRBNmRJyoylxY0b33Dpsk5kxcAl06+sSugl/OcbXAyW4H3d+dQAUMlRPEVzQCgd98gGrTFF6p
-thorn-05.oob.openstreetmap.org,thorn-05.oob,10.0.33.42 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgQCYjNImXo+2xnRT7T/JiHh+eNl8I5i/sjB4KBaHizKuJnwH4heLbPtmbI9ze9MV0IHJp/289kwT3bSgj0nY9zi9Ucdry0WtPgGQO4JbDZXzCBhwa6MhZVLAIOKU34fK6AIuZqzQJwXeJZuCIiwaoliUwY+QwNcX3rQho80eaK6XFg==
-orm.oob.openstreetmap.org,orm.oob,10.0.49.3 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAn68BVVd15SyHq1vdXYZukNkoxBPlNBgA8gcaXjlQg917A8gXcHaJQ04xSwt/jkbbvELNuvYDuw0EZAqQQHG1vYsXffg8bYrEq/WUs2+oc1O6iiR3xrzgDWAdefEVk+Fk8TXRGI3dy6IBpFoQ6ywvNCbFvVcB41FLRtBGOWdJFZM=
-ouroboros.oob.openstreetmap.org,ouroboros.oob,10.0.49.4 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC0b16+oF2QHYj+iIS2YT5VnH8KfdYckm1ujYSo5WitGONMqhN872W6krqYbW7GjFvrJ2d7GbNaY/3VeVURLumgWBnit77bExpga++/QYsE90DSoiQMeUT0Q4QuPWXcTIzAcGesda4VtQkTRBTt1UlmdEGBP3eDAqL2GoW4DBPCiQ==
-ramoth.oob.openstreetmap.org,ramoth.oob,10.0.49.5 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgnWJq8z9xvNFujhE0P040rCO1yEsH8pnQmGOGehIRcfclQBd2wOO22+8kpy04BMT9FaFdxjgNTUWtfCwT+oBsxbHIreahld34vFVCw/VSCiPEuUhBdZ+fN9hdLGygrnKxA1b2cIs532nm4LLDoP2VpM4RZuh6da+LV3eHnfDlZHO870=
-ramoth.oob.openstreetmap.org,ramoth.oob,10.0.49.5 ssh-dss AAAAB3NzaC1kc3MAAACBAMjYCKyJfA9/EQWTxwqqGBq88dAaWWG0j+ggoGEYuIWqcdA1NeF70BIiRGvAV5/oBy+p/snd0LAxDG6KnWglOo/0cjzcfys/RQl9kTa6gkcFPp9lUqRnuDF+y/egZVTU3KF376k930nNdODMe5PxECnZdC51158Zga9Hwj0+5nalAAAAFQDnh0Gx+gt+6Qc1r74FeNCiIPmzIQAAAIEAs81g5c2sF42ATY/gd5ustNXm82xfIAuRGeMCgxyXBvFM5UXuLnfOx8JVB8wu9eoSmxhDiuVX7ija5FaKAAucPBXWh/YImH+T3SOWLsxfDh8XglH4NvEtj1r+90VWbX/f1Qy7IsmmBolUCr32qD5cdeQ3JPxvUvO/TdSHaIgGK30AAACAZiVJOiM9mfMf05rAg9fjo+NKxL/jsbZ8ptTnNOFBNjq0XydXQF3Rnt01b/cUSv94VmuJgv9hq9L39nk/dSnBVQbKwIYyB0/NR2Fg0sYHpo4qj+7MFndv+ct9pVd+l9pmlEoR8soLeO1hSVeSmj9YvDzc74lx8FYMVE6+yed8ltw=
-spike-01.oob.openstreetmap.org,spike-01.oob,10.0.49.6 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDHhi90mKvMe+FL1pdzBPWUfC+a0ckv31Qou7Yby1Kn9xhrR5oHvyoT4bc/xPrYvaxRZUHWn+J66ZdylhyfCZf6/5g8xghJoYVAZJn9yCV0R7xw2fzHCgue3iS/Yrep2V3DRaXt/zy+PCe7wZX7InLLtp1rV/Vx2xG3lV91OGa4Zw==
-spike-01.oob.openstreetmap.org,spike-01.oob,10.0.49.6 ssh-dss AAAAB3NzaC1kc3MAAACBAOE5d8RsNmFZxWkcwXHisg5NowzVyvYjW/cXmDRkeN9r2gvjDRj+WU8CIo4rhVhbJIepEA/BUkzEyDBrBOydFa/pFH9KN+tRnSabRHaVweXr337KX9ltSGoPijSwUlDhVITMMSZ5v50tJ9bokyZEYbgpbzPo+slqgMFbR3fr1MvbAAAAFQDWzbv+xMTMOYcQQ92MCaQKtsXCJwAAAIBW02qjzbss0X9TACVhGHGbAy5DcfybmY8JZhfUgqR0xI5rCufUW5+dY7EQu3FlE8bC/R1rPrks7wngmut6xPMtkpcpMYFoxFPgP8/xfwkTNYMs2J5Vbrb6k6e1XMKt9AID+QzhEjTVxmwLKAT8uZGDZjY8ujYnQMbM3wPbCbv/MgAAAIB4xUK2Of6YBWBOpW/0GPfFH/of8Txv2ErpVmTSTOFaO7KD6x4jcKjn9nFMvVUhW/c52UYYcscE6uArd3XNbJBw/H58i26V8RooTkQVWhKNbp9ktXPh8yADNzVq/rRW6kvNYHZbbTev7WZ0NPvz2aIrTLKPcEcUwLq4wpNBe//1LA==
-spike-02.oob.openstreetmap.org,spike-02.oob,10.0.49.7 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDJfkctRhGPVyPY18EVcegsABPTC7PsCA6Pt2UOkkzANJKkwrOUJyn5GqgJYHkOb3hWqPlS89zdlV9kXlvTdUZ8QKw4xys/5H5+CWwbag0h1EpDR9S0xO9gIgX5DgyB5Y7oNS8o9AolF+hgyUdmBYO3ff+h7eu1PnqBn8TfquqVcw==
-spike-02.oob.openstreetmap.org,spike-02.oob,10.0.49.7 ssh-dss AAAAB3NzaC1kc3MAAACBAMxbg3AjYJcMX0jlgyXslqLbi3MV1zAVunNGqFOipJCW3thZ/D780MbQiXuXglqJQxWsELy+8RVVjt6/rcnZHORsH2H8M0/3WdlEUW0FxMUISXUAVtto0Fk1v4QznUtyxoKIg7sXktmreaNEcLBA7Le1bOBf/Oz14uQbmI4nycelAAAAFQDEMSn6sAPKhEYhYJiFYsDoV0aWfwAAAIAG9y+c73QbYqHBOdNISG22W0BYAnUj1L90lW44xNnmrVOc+CdTKG3VnAQcIc5BeB75sfE29JOmUGfR3/clCgCL54V8D+gEH3omtSG3eG7B+OoWhcUIoIfgO/3w2ZactdU8lA2qwSfZ0p7xLPsrDN4wuORPYFpoOU/vV9hG+dh7VQAAAIEAuk45eD65i9Gx6hHQuCoN5EGQHhL5qvO2gbShYLNqEhkDN+TmdTLK4Wbevy6tOdCrCRKP5zhoycbqm448hINFtwBPXGfRfhDsAGm075pMwljlh/LU3lSXbSU1RkmiXqjYqcjl0ntxkv2qA+zN7G1/oJK85pwScyiMo9kOuwyh3+M=
-spike-03.oob.openstreetmap.org,spike-03.oob,10.0.49.8 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCvTY6CDpJgBcU5T0l7Hmn6UkLZw1d0EQEPlcQM1UvLfdSKayVR79Yl31eVWFbA+R+QqQ8LKcmzx6ztWPuemW3Ym/gZ7NNYH10y1Rw9LywWhVnFOjKIBUVJmjdiuxftyCPveHu672k1KJ+bApXlA3/oMBmtCckr2Wod2qJDx7JIeQ==
-spike-03.oob.openstreetmap.org,spike-03.oob,10.0.49.8 ssh-dss AAAAB3NzaC1kc3MAAACBAKHL6HuJER/kKOFoGbPvQ0ghCw5lJ4ACsZHi4ptTwpBh1rx+/mmktTU6/U+cP8ocGo2XIuoCaBMfNK/eqrh37a8/fZah5+wxwJBWnZqncOhJT9EjRfvRtbJr8GRtCukNxX554zsQBSqCn9CIP6E62EqbYUf0qfROX5o3SZVu2WzFAAAAFQCWHnuBktRY7R5n2ZuCL1Cdx5hevQAAAIARZiVCIAKIJerBY4AnGADzRf/m21PkhksRIKcqge8vDI5z8MMgYkmtcrlqgGPEavnajBPlAF8DdDFRbx/4k8K5ZZdr+4ipp2++V7fbkg6n2MMwR7qTN3FpoNtLwXSHLlsueAArRW3RNlYdtx9wZppUq+cGlqr0J8jXS4UOLH3MdwAAAIA3Y4EPZv6PufNBppuegYI/gziypGwlNc//XODoIagXyDclGxGnqh36J+AUWxuILQeHRTZzdLCVazFZt+EGJeKI7/C3yJOkSp3vNnre4VYmGGRp1hcBKWDVCltjv+phRMXGiuGSQdqCy+AfkGSctNQafRnQuaL5hLBytHxbXIADhA==
+
+# Manually maintained records for Amsterdam
+
+switch1.ams.openstreetmap.org,switch1.ams,184.104.179.129,2001:470:1:fa1::1 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCbUecW/591rGCYtkdVTUgAKTBc+lEhraeMCau7CHqMkkUn+/pe68toDySdTaO8jua1q1asuEWH3MZ2AGAPSF+xhrqJLLPQmm0WdEAQfZChxQUoqCPqlWAuM5u+bAc3ntKjw2v2myoGGAqjL27QkZDP8qPdxvKcbm2YpPVOHP56jsyp/9BjVhIpWVmMhkOAfBSjdKU+uP+NueHrJ/AueoqucQE0txeo5Mmw7GlRuLTsMNDU3Khlhjs/2Q0QGiMXV6hQxj5AgnaDZMdSRbp8lXlctDZmipr7jVk3TL+knzySih5wJ7wmeZimW8Dhcxk6HBo2lGgPGdtQgttCF5ZUGcfF
+switch1.ams.openstreetmap.org,switch1.ams,184.104.179.129,2001:470:1:fa1::1 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFPNVsMuGWMe2OP9AIg0hqZLSJP8zyNHWqYrXd5Mnfr12XdhzWEAKLTD14ZnJcz/GBaE0ad3IjT+hVoS/GVtxpQ=
+switch1.ams.openstreetmap.org,switch1.ams,184.104.179.129,2001:470:1:fa1::1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA615MNtLzOv6qPfFsD0I6Pd0itshpHLAVImjt1ME4SM
+oob1.ams.openstreetmap.org,oob1.ams,10.0.48.102 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC2oeoe4olettjDauLuRiXRQVg5k6EO+PFfS9Ho3OzlOeYr1+h1SSPLkFtr20yOKcGXQcmYLjTbzvt/sbz2JUbfJHc2n7tMvQKK5ClVxLwqt2jpfSepGbG2KjG6vwxpkcDMH0bquzr/8ehpYmBwh3m8EARgcVNYoVL6J5OV4ILAtjNEllsrB71gitrarC8iqslRLVMjane9YKa7z0AGkwcT9w4qbcyuQ24rJF0Xo/IcraxVAYeX0Xtfx9rD3Zt1kHawaKYQdJM7RZvTtWcgCzHt738lFZ15Qj3at6vxxGpnduZiuHLB3PCW9yP4CFHm3Qs3TUyh3VqrNVFFdFvUXnP+DR3QK2E7TpViagZmXb+2AeCaLtrJ+1h0NEmQmliB4Zm4XKPsdS7k6Ul43pYQ5i1ipwZBNvhJrByQJ6UkpIjrwUlQBxXcEWGZaSL0sqqDQIYPizXZWOh7pQay2LxnHUVp0MZT30iVLYjptu9PcJ6CBwoKzhnVHPh7SON4uzDyMrk=
+oob1.ams.openstreetmap.org,oob1.ams,10.0.48.102 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFLujNadDWF9OqF//izQ3/jm4zElWb2nMjfpeiUVCYh/Jrsl07c1bRJlnSmoxL2H0xeHJXQh1E4PPy4o/5N4GfE=
+oob1.ams.openstreetmap.org,oob1.ams,10.0.48.102 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINxBm8YPJNtUIDh+0YWKY/5XKv8QKQBtF3ecqQcxIQNJ
+faffy.oob.openstreetmap.org,faffy.oob,10.0.49.3 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCuL6kBDuK+/xj40jp4ZP9HVoH1enU1W9MWO4Q0cxlD9sjHaz/mIbLhtPxElrw807QLsUdOx1IeD0jCLi9XAYYEF2xFFZ9DIP+qGp6hQ3XJrmOVgbDuckPjdvJWAxC5TVaWqwvHyp02biJCfSbOzsmjm2cOp03Cqq18HJOCfA3AxQ/zSQDSVemFoFPVeM67M9NgM64z1idPAvMVtW8Kd+unU/oE7V+Jil5TR5vwK+kVKEixxMtZfkJn0bNKVFWX5sJYmKWze+b95O+iQlsxmQW/p7UVM/3krKdBBT8+9b6UOv8TN0Yhopp86aXEgtvUOOyyimjqO3V5ogRMGj3b9G+9
+vhagar.oob.openstreetmap.org,10.0.49.5 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDJaXI71RCPjbni+WxBnOf2CzkLi0H5ARG1RxevLO5smM/9LbXVAVgcZRnI3egmbaJF7r6queHtrQq5y27+Rz9OEoJ/DWMS/qaGWMqj1f7LDv+H44juKAxmayOYkLJUnXN/AYITjpNSfLy0kuSo9cGpHVKjQZVFGv92b0c1CPrQ0WJ3Q8Y7ERc77b2PBQmxWow/3RHv6SoeT8riCfoU5Mnuld2aNjlJlEglf79QB8r7Xonx3TDfcr0+bGbvJNhYoMPPDXFC96wCpjvIDQu09BEM91/zP/VRE3E+bvIp0WRugU6vUYAAIcKuyQpON5Fs1kWaY4AZ6/4+Qdql5B8z8twz
dulcy.oob.openstreetmap.org,dulcy.oob,10.0.49.9 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgmlwXGPIPDqoMz4s5edr+G4iuBnCYcFXjY7Et9jG/ezI6aIKd9lEOXvnHJX5hrC21aqd06dhyMLwZN+eSjJhXNaLtYmm5P442H2ZnGca1KNSpF7yRVhn0eRpX39xWK3biVfMw64mzvV3636C1adCkgBwuaqCvz1EHm/KRrySfuETFLU=
-dulcy.oob.openstreetmap.org,dulcy.oob,10.0.49.9 ssh-dss AAAAB3NzaC1kc3MAAACBANcuNreghg/8rJAmfsdD3Rp58vN84Ee1oEFMgGSxF6+yEVTbXrjQoH632jiBXSayQLXGEzrVTsGaWgujK9xT7OinNa52ydnJ/WZp5qK5FdW95h5m7pnUE3Jmm2cPmYpEJW62OeMStmTGkK0EvN2wwRLuts9R1NK63tWjFWik7QmrAAAAFQDNtW3WKlCugOFZnjIh3fBuDakdlwAAAIAzy/pxXiix8yKhlb0LQJ1izilnn2IXRvAHv4aM6LAiq6QIDj2XyT9oTS/77BguCw39WhVG599eOSRckWXFgUT2p3pWBBuuDbLEhQqIc0KgufYh/ygUdjf7zs0O2jusFkLMPgF/0IgRs/ftb36ERn3KJ4C1P0v1ABk9t55Qs985WAAAAIBZFS2HS1ewjv+/jAdUH68zT0mNBctnrqM8ixqT1Xd2Tl7SKjl6Sz9yer+6+Gq7O50U0FBS0pQPo3f9msazQU6BFYCzuSFRIJQmH7uKGPHHA7mbuow6sEOhtXBzq1VfI4addXyWlYLKXxv94/gt9xlxLZHqU4ZZb3GPGbU7kKJA9g==
ironbelly.oob.openstreetmap.org,ironbelly.oob,10.0.49.10 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgwDkRqR1VRgHOON8M7YCNnIG8k0zukAN/r4L5fPKTvWmdhe17UnxywPc+TySjXqNsXQ/jPLGvpO5uoSG3dgT2N7NUdAtdL4Enb87dX7yTbJTJzMMxTb9HSI1SL2/5iSefyAVVo1+R8DMmFqTWa2eFHoD9IoxFSNSTarTZQgmH1oZYoZX
-ironbelly.oob.openstreetmap.org,ironbelly.oob,10.0.49.10 ssh-dss AAAAB3NzaC1kc3MAAACBAJKKtKZBECA+wtvYtrEeMyTzkm3X/4IfC6E8NcnZouMCHYn3F964+pG7mRskZAi7P95VwJYx6TLkiK/MNKIh8mk8M4Xxu2USIXblkTPraPYHyVgTkfZit6F9qTR8cAOlHtoY+9GgKmWMLC+xeOgPtoERvUyuuprXsAztZ9C2BKWjAAAAFQDnPXN3n2g1xxsYZsaQpdPuijb1tQAAAIA7/IpFy3mSgpu/TmmBuYLccdRTCNt493U3wMLb/JdUBu4h1FM6J5DSozcQ70ATglpLLYa3Ru5ztv87Esu8c7CH/TAH+GZ5/3LJtS//HJDt+53yy4CgwO8pcKbYo0rfRy4/QdFXWeBUtM2XN4hHvbaBJ0fzP1gXI1GHvz3OQxWICgAAAIAvZVlk6GX+uGpqLdW4F1ctkuqUnkIGzRziJ9Gk46vOOFCPxU8bUXLGzvC7Zv3SOR04YH7/LDMUof2y68EOCbH9YT8mHNqLdZ9TxOWv8wUaDX5O9J8JXngLwl+U+ONitseg/PrEZKmP2/cR42pFwuTzb59+NSkEVAa0ZK6+2FkWog==
spike-06.oob.openstreetmap.org,spike-06.oob,10.0.49.11 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDwQVb/cYgKp21vw6+jKr5TLAD77oKunbFbjvwPL34iLRDqdJcEOdJBV1A63ZDUWSWjDUrTa0kyneoiYdD876EpuspZ4bPgmiHBvug5NR3usxa8PAsia1K+fONAGi3+s96H6Us273KHNH5QwyBNDyYaDDjIECkydU4bQT0FSX0j32eAHI62ZO/H82fUyL20PIK/nCUaJUd+5iXgcTfjP+eL66ghgPCgXGF99/w2+3EUxP2IN9J2yI57H/rYn3rj+NdZyQuzc0TAToT341cYh2+a8R1Sb/DEFiMZFE2hJ2NeVEaBYxPSlFfhRtlB6ArXg5QL7e7UScQh/ZHLU26A1ZaB
-spike-06.oob.openstreetmap.org,spike-06.oob,10.0.49.11 ssh-dss AAAAB3NzaC1kc3MAAACBAKwUXFxncoW/AmYePSswZkqbHJDN5zI6MblYRtyLwSzfdthD8KCiDnoG+6opsy18jaX+sX0PTz8hfNVUPCMhtiTSgbGqZuQbriT1z8x3yRbGShqH1ZGC2Tt8x8k7ft17Z1tgnsnmueMrGekks6/kMZWYl+zrHXbrKCM4uPIHjK7DAAAAFQCOmXTNMg+q+8BybEEHDtWH0hbnXQAAAIBhZi+1jUaHu0UEtKnPRnChDyPrWXpgwVOM+goAZCOxfObI6PcxrIhB31gRPWNETR0UzMb2K9t1oCNdyyq7Y2TdFHEVHOTaBTWS5C9Bvtz8CHSou8mibH9sIhK2H8FevdQPOZHeUxQRSx+JzCL+f3qMovs05xVBNhUHO5XLtzIKdgAAAIAGlmX7cp+zx8D2vPiZEcczjJIgK2DvAu7t3ZAemcX5utUNKh0By7xxT8DqzIPYRvoAI+//4xqt11jIdO7KADc28uyv6oBAbB8DwhlbRONM9O84tqBTIxu0bQXtsYpkTAQvLlrDXMYDx5aYLpP1haTbGgdtjbDCz4FH1Qi7cBN0kw==
spike-07.oob.openstreetmap.org,spike-07.oob,10.0.49.12 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCxLxAbMPZw+LgzB8JmTLLxqc6CZXYA3Wo18RM02+EnmtRX6AAf/VFb7E/VpgHfZecwnFK7u21R47+fFdHCb8EDYGeWbOYoEOYMoDh26H8/aFPHbldgG0xs9EwfTryWB7iZ2sD9nLv+nBpDkFXVq53kscmDlUKQrvUyj/zR55xGxcq0ruu3w05ZeGx5I6HRY0xeK+6H4s6sZtF24Zm3CttQ5M7ADgWffE35ZwA9tEdioM3J3c5EcV4HMdhl7wame6pID9+FpDEtcts5z5sfW9Y0yx3FHrXCxRWxHRbyFG9/+4RNwKJBRZrdb+VSLlrYVUFLEfb1AhOxr8ZfSsJU1V0V
-spike-07.oob.openstreetmap.org,spike-07.oob,10.0.49.12 ssh-dss AAAAB3NzaC1kc3MAAACBAKzH4llCRo3t5ifkL9qB1KoWcAw1ROGVAJBwE0GkFZRQvzGQ7CE4anpFdv8BVlUbFx9N6batsC00ERDL9ReWQXWMa1oHr9AJ5Prpgt+azn3AFrKhhkMQZegjnZ0Ddsl/XSmFbRbJX5cnvrSIBL5nEC6kBCVFDiuH8MlsWaUsvUtbAAAAFQCWQKlZ5osk9BZKsnss/W+Mv653RwAAAIEAmbM4n4Sl77tGuTQZrlojpjEF/qm4iUpnAwbE93e2EIr2thnM+6QYtzYZ6VXSXwrh4UW6d9lL2mgSxQnY1HiM37y6e/oNFrsluK5j7AhxAYm4bHT+UpqyU/zl3eUlTdvBxhkTjQTT+wTsBgTwu5zZaJrlEPzoYkCQNJRS5AAw0gAAAACATzzX9K2AYRf7h8gK90abOmp/LYNO9ghhbhifsIrIxfShsFubUSfRO+m9e9wG2/1kwQY2VuVpdM86wwFvjHFlo2VHQkIl1JkP8pmVKs/QKSo4WSDY7aO8bpQK2Xx7QC06PUnllgXsPcyted8BGCoTLMVRkmukMwWls+Qw4fr7z18=
spike-08.oob.openstreetmap.org,spike-08.oob,10.0.49.13 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCm7BnJ/+IKh/uAI3vIjIlkqq83jFkuxfxPuMty9/jhm9XoVbf+nqTfRQ1zMZn+bqjEjLRFTU3uwsjI61fk1Uxru34JKoJM3axNPK0S0TH6Gh08oLoBCCOti1/tTAiYaSLFfauucnJeEMkKsmIaM4LzawphkIuWu5kUv0LteuycqJAXZKr4jAIYZuxQZ2e3ofdzQoXIjXbEg/9EWyMA+zbUYlAZpELicTOQywhpez+TpZ8GUnMuya7jv5pTWfiTbSkToF0HTrKUxIEg1HYruBs+0OYI+LbABe93z/fAk3j31y3FAPEnR7vqbM7mc4DLSwgtKsKkpGGGeVHLEJtHVhhD
-spike-08.oob.openstreetmap.org,spike-08.oob,10.0.49.13 ssh-dss AAAAB3NzaC1kc3MAAACBAKJKB5ukyM8DRC6fbpXb3KEqSq4CmBqrlqXCFaktWKFerKUJWx5No/xWn6n0H46FwpznH07Dt/Mom6XuN2A0i/ZD1pE0VHnQif23+L3PBu7t3cDPVJkj+eYVB2avPPrwLGhOLOss0oKnBwhOgK3FTerCRUN5MuczzPY8xtz7w495AAAAFQCj87X4s3sLxHybJmuRFEuc68Zd8wAAAIEAhajd+H+3uVBAIKdWpn6GoU6bP0y9/ERnz1GKp+fBlTVHT+eSc1E567HqVErHxc7QSFIBmdlF88MyS0izQSAFKdzevJWqUbDeUKtcB26hGGrvHOp1dLsoALpuUDhOZvKIzehp5linYJmgnN91piZ3BlyxT1acr4zdceIGNL7rJtwAAACAYlD2EQvr2JI99MooGimqEYP/zC/HhChmtCEIJ/XQrOuKxBL4AlegFNECXBMn4JHFbdyb59LYvVlykuCgLgNY2EKObgltKJ5WLmzIRpUTBW2TlwAQiRnGqA6TGUpTTlKZFqAnRSqOJfcvQw9E4HwlN5TeOT5kxN9j1duUaV5WLx0=
-tabaluga.oob.openstreetmap.org,tabaluga.oob,10.0.49.14 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQChE4Wu5bUAgtJxrappT9kZeftw9gdj+D0QmisCGHbLsDxDnww7g5gplexQOf5aEtLon5NU4HNixcEFZ+/RtEtTuVaC7wAdNF1HOdOecexvHcEFlR6KPrdAKykTyo4hWYUd4Uz38zp160V//ViAgylpvU2dhGhAWKcxgmamNMz9iPd99T0fW9bXAzpiB+yBuBskD+JyA9bQu56mfIW4u4rh1xgPBRyUdorqetM97QJ/fcdkN0m4qVda9qP0J5DUli6Cq8IbEbv87r87VPV9o/WOKGBJtclXdUuF9aLAvP3p5V+OuxqUCtvy2r6LDBvVURURb2/VXzn0O9x2pWE6uPeD
-tabaluga.oob.openstreetmap.org,tabaluga.oob,10.0.49.14 ssh-dss AAAAB3NzaC1kc3MAAACBAIQNHSK0uo1CehCFag09Hd+bJ+CDD0LPWoE/6B8Ye3woVQw8XhJPIygWyHlsFo4rbgkTnvz4ooKTUHnisEIoAA6hlqFTVP1LQQarkmba5Gf05x42hYKjM6mYvcoDMAdnkPueqKIa2CQVNCg3sopI2isxaUUWPEqrVeTMgI40ofd7AAAAFQCSNIl/McB7R/7q4fFxZ2dVGtvJGwAAAIBNRHSJrnm4IDYufJetkWyn4KEIkycUMDs1WE1H1LbtmsIaBAGaz1QJKclPCin+hCv/Rne4oPoZWGl3SqB7hjBkvKUOKRaMp4eG1YCpEvAhgNIFjPkgdekctQ1H6/+7CkQmMVelh78cUMOUYEoky7ISiaKUT3z8O9EEjPIndreNBQAAAIAQeqPxG9B+RJtcOqnW5d9M8VVUNeW10A2R2AMtTEH+/hjaoXUPpL3bQ0Fl3aWQKYJMRpOM64GgLswEhxeWf0PzSAi5CwBmyhIEUJpJ0jHOYSUXC6sLpBMV1ad4gF/63CBAgL1fUnQ/FWDtZwDEnBksDbYSS6EJB5m1o1vOx3SHWw==
odin.oob.openstreetmap.org,odin.oob,10.0.49.15 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCeK2EVK4rbsdoTq84Cl5kLhbJk7gbaNav61yFuSKfSsizzbH/tzxmiFA7mtB39WU/BlFsTHAg1mHY7cCPE01E811CDPIQhZGEyloh5ftbTACCcGAjKBhYpwTPEteBqlIk3lpN1TNTsnJSYaQay3rbOQ+IXTb8nzKYjTgANQ6QXxSq4BfuRmvMRlNw7ZuIerhs8OL2G/pxldL6AYDPDFXBs9mvvqqS0fw8rzxkjFNUc/z9odFoChtlZVbp33/LTIBQU1dY/XTxaekErjT7H93KG9NP8mmIFZtU8oRo8553ogTYVxFr6hD5D6KkbveaFU9oBDRYlJPWtdHksF8RAEpjN
-odin.oob.openstreetmap.org,odin.oob,10.0.49.15 ssh-dss AAAAB3NzaC1kc3MAAACBAMxXgZGeLxWyQCErmy0aGppk2/xHj3GTATPCQgf/Mtm5PYK7c3x8Z/fEop/BBnY2/YDE709g28Tv+61I4SD9D33OO6ABPEapHEwqp3CIYuA8+JFJhuo6Sz9h9bca6fx/KVjdDq9wbmx5IOqEFQlBoCSGJvYw5pTptVFN+nLeiTLjAAAAFQDt76BO4R+GaDn6/SeJvP3xAuqkmwAAAIEAgbhpMfB2Gk+babYDnWTWMkFO1FObUdi8/3NmiS1XUPCzdGkL1h2psoQIMXFtrNfEzSPx320rjC17T+JD1KGzXTBsPSd49MhznMc13JK2YT6KJm3io1CLKuzje4SxrpddM1Uvs/sOLmeAbdNqlUsAM8KUedEYTo/SXeVecos6dboAAACAasbTSjiTPW3NwH1yrEV8xWFCAmsmAPvqwGjaLjrrDdNQCbJ0KHMY+lbUAmT6oZ5qcrwwc2A6B+/v9XBISiT5XWELdP56bhuDcWC78aJDdtfDK1xuMtsHX5tpQcKB7IrPI+2UYVhz7zosvcCbn8FukgDx8sEcp28rHaFB5WPCjig=
-lockheed.oob.openstreetmap.org,lockheed.oob,10.0.49.16 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgQCFBaTPsbNtWlUSsGnRzObp3NVC6MOro10p4qSXB0kwAB+hQx/IrIH8BjduR+b6Uv2cm/UMnGRzS/1lGYe15cSs0V/IOUyXdVeX+jB0TXzS4hTqclGKJ0Ay2WEsgW27IdPxIjQg/W77s9AZ2UlyEtT7gK2oergD60yUvRfLLJioYA==
+norbert.oob.openstreetmap.org,norbert.oob,10.0.49.17 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDAHaxesONNY+jIQmZKVKjsg5PPTYytFpBG9qx5Qjgk7PoPt4VcxZu0X3snv6toy2s4zjmnIo7+T014+ihKF5RzzYB3sRwHgx2QIXp9zjCkeB8HCSyMsnKWUoJcyxDrVy0gS0GgbmzIAL3n47budeyxYW20Bk9iy+b4z2KUGJnMrmhJ76eZkawtsr1DxRIrCWDrXNz66+msk7v/3DDUZFAACkPEF83YVECiNsBeKn5nm82W16OEFKOMsQXM65DjPTzH4iKajlA2j8DTf5qOtgiGGtLVQ8b5erwibgbXFfd1wWsqxhEP25z5omnheSujCkhYoZJ4+larVgqU+CUvCHE7
+snap-01.oob.openstreetmap.org,snap-01.oob,10.0.49.49 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDcKedgjsKRd3zPnZkJNL7iZYHay+KBd73bw4PjyHmblyUOcdtMx5yEntBHGcWAs5lwc4mNZgKbSJfuuW142oq+r+3I8UzcvYQGJKAvR5quKCn/c+iDkX56SQvh7SOtgf0K2K0dfHdQEh/jw56AewKcPxgCV5vBJ63ce0gETq3/Fj6mJwIYLU1kjyJiyusng9EWlgbodx8ma1zFM0dlxdHxeMkE38pcnrpOxNhV7qbGY9doU2VFUPQnCQOzpUtLr6n0J8l/1ubPnBsN/VAAYGMNbxwGgpUt+Hpwgl7dcn+1FQfFUUL54inUuP7Y2EV1bEY/WyhfLDkMRwgm+X96QctT
karm.oob.openstreetmap.org,karm.oob,10.0.49.50 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgnWJq8z9xvNFujhE0P040rCO1yEsH8pnQmGOGehIRcfclQBd2wOO22+8kpy04BMT9FaFdxjgNTUWtfCwT+oBsxbHIreahld34vFVCw/VSCiPEuUhBdZ+fN9hdLGygrnKxA1b2cIs532nm4LLDoP2VpM4RZuh6da+LV3eHnfDlZHO870=
-karm.oob.openstreetmap.org,karm.oob,10.0.49.50 ssh-dss AAAAB3NzaC1kc3MAAACBAMjYCKyJfA9/EQWTxwqqGBq88dAaWWG0j+ggoGEYuIWqcdA1NeF70BIiRGvAV5/oBy+p/snd0LAxDG6KnWglOo/0cjzcfys/RQl9kTa6gkcFPp9lUqRnuDF+y/egZVTU3KF376k930nNdODMe5PxECnZdC51158Zga9Hwj0+5nalAAAAFQDnh0Gx+gt+6Qc1r74FeNCiIPmzIQAAAIEAs81g5c2sF42ATY/gd5ustNXm82xfIAuRGeMCgxyXBvFM5UXuLnfOx8JVB8wu9eoSmxhDiuVX7ija5FaKAAucPBXWh/YImH+T3SOWLsxfDh8XglH4NvEtj1r+90VWbX/f1Qy7IsmmBolUCr32qD5cdeQ3JPxvUvO/TdSHaIgGK30AAACAZiVJOiM9mfMf05rAg9fjo+NKxL/jsbZ8ptTnNOFBNjq0XydXQF3Rnt01b/cUSv94VmuJgv9hq9L39nk/dSnBVQbKwIYyB0/NR2Fg0sYHpo4qj+7MFndv+ct9pVd+l9pmlEoR8soLeO1hSVeSmj9YvDzc74lx8FYMVE6+yed8ltw=
-thorn-02.oob.openstreetmap.org,thorn-02.oob,10.0.49.52 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgEitEET7IzW9j0lgxcgXT9JgzDR/cbQdlYSwV6rcWvHW9cz1ArWmJ6BY2AJ6CG3wTznVbHPupiFKf0jvkX0omKu8K90f5FJc2/BkUP4aG72YmAoPVe4bflGykvKJE9Rd4BDyPWGqI955Okp3VGCEKXBS/fwnoOZlei+9ex334hK2
-thorn-03.oob.openstreetmap.org,thorn-03.oob,10.0.49.53 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgBrDGGrP1jST/axY9UTs1q0ljkET93/vIitbc/C87pe08ccQUL/PUn0GTrVhXps2Q2nfg2IuI32vYYy0lNKXD53NOpu5G0ZxEB6BYxwejwD5YLZhJQD1mtZ5JvyAPeeWfZa15ZRoI0qzg9RxzB5bp4cRKtHxFcGRAj1jjHkN+80x
+
+# Manually maintained records for Dublin
+
+switch1.dub.openstreetmap.org,switch1.dub,184.104.226.97,2001:470:1:b3b::1 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDFA/DoB19FSMBmhqWa16pEfuuwvBVZhpcS5I/tWi6doLBn2wTIH5CJpUMvrRCnS6EzwpZuNLHDDoBDK4bBJNKi7CnqwaqIPqC7uLYKUDJ+sinYhhp2pw+p5ba5j2dLfGzF4Ccz51jEp/Zu13xtk14X5vaLIsluegZA/hOQLakTYWw3+Hc2B70/+vwsnaL74ZsFJHvB9fhozY9hi/cG5Ka0rTpDkTJFSPHRjJ9VMAqPxvPhupt80748FSmp0DRa+AK533txyj8b1phzi7jcg6+K0T9pj5prRxhLCiAiMK5h9WDJTs9fp0pk9NdxhXFwUpEoqIuGQPZy15GKk9yLysDJ
+switch1.dub.openstreetmap.org,switch1.dub,184.104.226.97,2001:470:1:b3b::1 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPif4ShP8AO/RlPkQ+cIgVH+mcwVs+c0VRx9vYUqv4kSYvQ/3GXIQ63vfRdkiRZbKqEsGV51yN4q63OcfH+211w=
+switch1.dub.openstreetmap.org,switch1.dub,184.104.226.97,2001:470:1:b3b::1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIZkVZvRpuvd4KXRli1qLaBDtiN8MJxz0NycpOuFsWa+
+pdu1.dub.openstreetmap.org,pdu1.dub,10.0.64.100 ssh-rsa AAAAB3NzaC1yc2EAAAACAQEAAAEBAN5kJioLsL+Oant6nkdwDyFoAmzJGFEUKaL4gTScrQvRX26oJyI9kBDCM3PHgkVqfA6mj96z4PU6WZuK7fz5QUAE4C3vzgnJ2rew/jGTaf45gFj9GgdRD6ilwFrmCaJtLmm+BmuYjWFXZSkVm0vhbo5lRxtrykjicowYuRFj6mm2MXcDdzua3FjnwEwKK+ArBtHPBnuheyPsaZ55wnXJRnN19gbMYPYfJ0XsN1tRkF09o8Jljpziyr7Z0VIfw7O8vC6t5wz1hp8wSB3QMSuNG0Ze0zwoVyxG6h8Uuna5N9SIOQrQDyjPaIb0wpZItAzfjttFvFt6OPpp68NA+CKDV88=
+pdu2.dub.openstreetmap.org,pdu1.dub,10.0.64.101 ssh-rsa AAAAB3NzaC1yc2EAAAACAQEAAAEBAMmzndbQ6jQLNiVJJH9dpz6kOB+xhMM3Yyp/lvSDZ9GwrX04I8KALOTHhW9/Pzq5X4EhcI4aFy6zEspFI5JOnntjWdM/gXBSqG7QW4r2BSaGmmqAsjzHi3uJ8R76oMd2ckI3fsLIX/x2AVo72M0lq1nuTjeC296vGZByUPUXtq/dKN+pW7wFvCljuFp23Y+uNY7jBTqsoTE6R7FrTJnLHMK5na8wVXY+bDWXJeX4knGIg/qDxkK9kCWv+Ghq6wC4D9oJlF5URC+MpZ8nfD7wB1YVVHhwlmnbAOp9OsZNVZNX3V++5WDtWmFGPCMdxwnpfC8MuPwy2HnLZcAWp0mA8aM=
+oob1.dub.openstreetmap.org,oob1.dub,10.0.64.102 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCZrRoYLxml8E86L8ZsKWtLPvVhzt0ng5upbGR/ZE93p1StVGE/rGECjrttuO0xiu3BsIiKtjil36gg0qHnYvZsbVakJ3nLvaA7wSiIQ4rfFP57YlYAaIR/Hgjju9PMFcsQj+mQPiowj6f7W/NdxTVuDBIJjN2D+V0e3KMHrJE4frEcAxUsJBYTfBHdR7qriRqhZDKLdZMnDcurf02PpdOKC0lqlaBKEIDHnj3451R8xOolC3HsFKKfy5CgTqj5+hvb1huzZFGWjasP5cs6/HnbgcOo6qhtrLtboo7AFqpW1oDGTx7A/004bWJYRRhSU+BtmHzchPdyov6XtyaLz7GIWycJkLzap24gb8nPOzDINNiY7IVYZejEja03h/jncptONg1NVn7rIrd9CwO4rJKAndDDjtgZKv4HoXr3RR9+t0Zx+6HAAnNuOnIL906H/bYBFSP5LdgfnLPQoPdFLs/hUjRY1vAKCh4bvLC+GXwdhga93tbtv6cbwUG37gob3/8=
+oob1.dub.openstreetmap.org,oob1.dub,10.0.64.102 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEn1uwIVWRyNma7X/OKwiqUjaf54eooToWM/0x6kjmIJcl5A4wmzCKG6iVvZezwfRPQo4jbz460QPLzJxb+pBYU=
+oob1.dub.openstreetmap.org,oob1.dub,10.0.64.102 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILvhhWXsbYCeIaQkMVEdlljr8GpzEL4taVWxvRzJa4ap
+fafnir.oob.openstreetmap.org,fafnir.oob,10.0.65.2 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC5myokF4M8yOu2EtUoos0CVp42V3BBx14BErSqdtWwPkgQIOxgvaUOkoFLUwtXW5pm1+4WIcvweT0OVNHpEQSftWlTJqn2Wt5pM8wkpvc3hoq8oqzP0qboW5KCQ+WODClEV3btmQMdAZk+BB6EURS5asE8kqEJsfFx9HnVTG1NZLndrTvdfq64pQa2k+r1AvA1B2bv/ehQEte4oaS3Y8eKCBr8HowKcOUzO8sw692yBaT3BdjI7joX8GpQhm0YlrWtBTPDKLiyxLmTp8AO4mQa7Ezmm/LgTRXpsZs/lDK8/Bwv9h+isKO8HQnmNfGLxpM//9FRohFrcol6RnCFExO5
+spike-01.oob.openstreetmap.org,spike-01.oob,10.0.65.3 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDIrpo9i/nmFZ/7/HSADKEytQhaip5mOERFf+JgenyYF7xQorX2NnuFI9QRoq+n7Xfp11p3kNYjeyZoWUVv/T1y27WgvOyH674fuIhFbdTzuww3upRVEJcbG06mAQZXcxXqlB3ceidtWzbB0/S5oNNF3aL6Zij+lAkgxwguIb7OVM5s80ASEtVCTdugftKx6rshzpF6bKsyqbEQhQOaNFzhEArGHzJldNwM9FHoDHMnpKyIX4Rd2dwp/GaAn8BIlpFJ9la9fukGsBi7fgW992Dfi6CG/aH5Gdnu10msiFd6uL3GpabUIckJTz1Ou6LDNzcsRq2U4trCSzlrAsc3z3Vt
+spike-02.oob.openstreetmap.org,spike-02.oob,10.0.65.4 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDXlO0w/s1h99D261F0UTEHFrigmhntNOIk5BKwUsEhPBK1yIoV70hU86J3/leLFa2WB8b17SrhfMpooDuM7ImtNkdzoY/pGaQ4Mukxwy0mLgAHhgJbcLEPVUBKg2nw8ZdkMgi8JvYyHj4wSgPTZ4TftdihFJUyaHUOAgfvRS0v9CraAGaRbI1nIDfcRu+zEolmtCJ/JGW6FJW4upBHcZ5EX8E3xYQtVzqG84YRERni9o+beNF/LOtZbfeYdKGhNguRBdILVio8+uIKeSjDGQ++/dMOfQygb6hQT87FHJdLxjr4T8qSVPOaUHxNivj0dUdgKenVDGGPCo729vGYZwy9
+spike-03.oob.openstreetmap.org,spike-03.oob,10.0.65.5 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKNLVCJAoMnqNDTeQiBvbr/K8IGNnxObFsyIIdKQwJBPrgZIaJNNTmQLA7S+qiVrfhreBaJA2Rbz+iEiXvKz5195Wxsu1voxx+vvhoYeaC3e7M3KECDtB+wPfxoWLMXrvhtu5599M3P7HBFiz1IpwsWL6sL/N6id3NAqZiBlEYcPkhzhoqA5We/wf5AM50patjhYVT7VdV2vYts/MssqiQQvHaGAB6jkCGwenOKKsbA3hXzB5dHEh0KaF+0O+4E/UUDEQcBBXuBxAqDCLdrgvBmW9e7uw3CrOVIOR1ZQLsbIPh2R0KEiUipE4T92v/67o3xaS9u82mgHBK42gIGqLv
+idris.oob.openstreetmap.org,idris.oob,10.0.65.6 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCiPCJ3dA6oh92HgSktihP27uOb3NP92u5+3dMSdt6v+d+wgsuKzStUZeoDivLgV2Utkw1Ax4CuzCaYSFJ3JGYwpFY9/ifds5O5SuAOPjgNDzy0ODYKCbur6L3pt69x2P6SnbzA5FfJeCpusJBzT9Hi4ZFuL+XHVti9j+oaK4Ipw39k9xcZwzpuHqwSWs7GFEYJpIvgv1C4MUBMgYcsne/SEEYEE29dzERDR0Lc/tcZK/WHh7hgM9TbJV4BkDF+BVwxnKrbPqUZOJMW9IrdPHhHS7esDglJFKPpZEOy8biLeYXrvRYb9E0pSu7iEbpIro3WG7+lKpfeHAtxLOTarKLr
+konqi.oob.openstreetmap.org,konqi.oob,10.0.65.7 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCTpZOi5g9Od2iDo4FEylFN1v7KYiX3//L7eAi8cafAYNipnRVl+dwDrgXJ3qK1QLSRia9eLWyWTFxh8yOCnHq2uH+5vUlaxY1GY1V+ABNPQGIZDYCAGOQiWrTg9L54sjtQAe0oLBI+e4NDPUSuUgNOgxDkSDKOyxSMRmF8ti7V/OFHoXc3VbAgcngLx/P2neOnl7lnacgDfgyEPARHs/c+mloKKcA3o83Dkcej/pmw0uea8ZkpicGNow+fBy0RUDE2HW/pH5kDfKBTS+QsXEC78d/U3FRDoxbrcJ+DlPv9nk1WSsp343vJ9Ipv49HCsf7hn3H4jGPVIKvbeRLDpMQz
+naga.oob.openstreetmap.org,naga.oob,10.0.65.8 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCinNNW6qam2H2ktHcOz0yruZ+tdvgbHE5Sv4to5blnP5XcbNhjMC2v0dgvgYCjqwWByZV6PU8MbWVcfrrnVJLjHNt2PYpp7oAFotf0+pf+dXEhQaZtoBrH+LcmNlXOmtSamjaHKFEyDjkU00YcxBZbf8+wP4U8+mgfj2thtGSAP6bDBWowpCCn9/NAOd2rw/4wUmSwaplAKbu0LVVD1yLVozdCcKFh6DNI5dLKcxGB4Xh17ifzB3kW7ztDi2a0ENKGQWzgBM1wcwjSxzdp1s+japwBywfvJIJHOuXDTHPAnoGey/q91m6pCHv9UaB3xbQeUGbETg24qV1PI7MwyhRZ
+culebre.oob.openstreetmap.org,culebre.oob,10.0.65.9 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCCagcuY4af7L3AqMl29xe5em3SUNYQcq+IPnXjbdVBIR3JXMizGPNLov/9PB8sNXOKb4ZapQTc1M2Kzdv7oqyXzfALEgaDOVOd74q9UPh8a9gpevgD8w+TVgnIHP7S26BWpvjaaHp47NiP8npsENAwRcBYkfjZcvCbHccX95efe7ypAiR18An4Zf/hNPL7pl2HJ1c6CSONboC7JovX5YhdRfAXJvSgRgrV809LTKXnTYNSwFk6BiosiY6bw0HT/CHk3DvojvyHb53Ti8ynCAAkylAoScdNFxnG+TMYH4U223EUXLdsCv0E0QkIAxo/Sj7lvwONtZebMKb0aYpXsCaT
+horntail.oob.openstreetmap.org,horntail.oob,10.0.65.10 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDuMo/aMNMWT1Wjr2ac7/sJFtzzJqijdGA3yZR96xPgY3zZX4qQwT1dmr2xU8i7K8EcLuS4oVU6JVNzfLGZycAJUNgA6/yg7FgpmibfY1pinI+7jnEJNH+hp8RuVY30ZNh2iKelNuN3RXKNxKd3tc2eEOZnyv6PcDnwIjL1vML/jezAsQzZtkx6zjPo/pb9jscQTA/rqd9Fv0E2IGrX6Klkz7Z8EXPW2pBK2hURA+9q+dr4RI2Y3hTmg5ynSD3mwgFiRRIt2An0DgBMciC3EnHn9fbApCSTa+O44R8Fr8ZbsYCqM7HV4jDRVFy4kPbqlx6j6r3zQ1SXgHfWeT8lpsdp
+jakelong.oob.openstreetmap.org,jakelong.oob,10.0.65.12 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+HV+Z3bTWwicg7+3coDi0IhMuL6+JSVeqMFkz2GI6jRPsBPCJWFhpfCfzFsHOsyu+BImw2bkEqCnIj1wxwFe0nDwyWEs3CgP06K0BBFcrRInRsn7GNHAzXKBsBRkS5azyA5dWnpv92jnMJUrXmbdN1d2uzb1PVxxSre9ChFcQXSQ5jRikE8dvVHOf6rdKKLuErkLanfydVIZbH6noDWgx3bQAObKzxLg4hf6ki4cTnNbhFB5exM8ZvD9aWgf/jAZ52BDBiVYaf3/qApdeTfeFcwQ7xtbKNcGWmcfWG6ryCTph6QRTuv8yST+V7eNUfWwwd+2ZqDvLzBQmL1YChojz
+longma.oob.openstreetmap.org,longma.oob,10.0.65.13 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDA2up2Io+unbTK6ZTnO9Z81L5ptWIy1O1qwtupI6vCCjV5fTPAdFxvfK9hSfDnlWuemtPTcFTZTONU1rGRrIl0MRDYZVBkzVFZEg0z1Fc8yBw3XV1m+H+X5YmDQ9QrWMefQXxvB9CpirZGrv9tVOURtGM7epqsr509FFqiQXZZcdlfM+BpbkF1KV8MQIUf7BRhAqei0HVixuQ4ntm75DL6qE0PS2l+eiYVALGzUV5f+DmnXovr3VCQMrD/R7FNTzwEApnbLZwUZ3Y1YP3tfQCSxLH8g0R0ymIWkzWCyzQLdjfX8WiPOsPXbzqGO+0r1ku1oA/Xk4tsRiW6/mEPotAP
+smaug.oob.openstreetmap.org,smaug.oob,10.0.65.14 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6Td4ugFZ3Ythg7AITMkITw79k5un1WnNhtwWtMnfkGscIBLw0ce4EWFYcNkX9YV9SHz3/6BXQuNkmDJQnu7NxCS5dWKWa02FulggbThWxbgZXt4oWF81VsJrMIDLCN8742Dujjg5L7K6IBG/M6ldypSs09cIo6zBDqp5qUns/y8N6DgsQXFtZg8AjgLEqadOgKJsk7K1S7JdQmKI6fPlMJt966KuqiAkEOK0V8UqLoZVKnI2OWLXNDyIjuq9jeHAqePoy4wxrXTg9DFZ/Txnf35B9bHtn99czSTWOWofvc3C4etJzrtd718CYCf87LFZeip4h2ZsOhnprtbwrZ2FN
+muirdris.oob.openstreetmap.org,muirdris.oob,10.0.65.15 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCnKmAEwBGFvZ7vdlr2JU40Fnc3G1KXtmJURbVzWSNoPe7OEEmPITikyb1tAe1fZI1O6awdhc+8u9sgho3SU5E+c966EyERAPpkGtfn4r00B7PNPPLdtJDFFZMHRDPlu6lBpHEQHAz9degpyCeiCI2tMd4Fhq+QnwwokymcK0JyEqqtV6ijXGNf5UGGuP7VzuynGLTCMZAGhKG5hMT1xWwv/Ws9u7Y9glhVo9Bf2p6bdpEnmgjo7Ai0SKPxpf+ar5x7aBLWscqX/ud0hykvNVY7GvsU2OvQfjYdVRd0aAGAw5qZf6znjIjTt02RZcfEJvWeFUdS0ShMABiRGM266b9Z
+snap-03.oob.openstreetmap.org,snap-03.oob,10.0.65.50 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDUrmWEptEG/L/k2f6haLRtvJnJCFTQWxAY1Nt3yXXAsyum0Egx4ks/Y0fNmTTppxzd8+2coFCeXDXoD3woZCMI/m/Sh20jg9J8/PhESA5kHkNgCqgy9UNNMcvNXEd9djIohM4Q45J2hZ7OFr3/p8BXbP5NgSj2wRXFtctONr+0wzsj4ThhxW5J35ZmvZWXXVbP7zqgesVHfmMTejknNghBp5qniwlzkD/kl8+jKWnSvFyPrKFJvwArEy2NjnrqquTpQcxsX6bwfP4piuQ3PRzHqW6NqQmA6iuqVHGko/uwJ4h9zAJgmS1BEZ33OFGpVRcIqNiNz0uEWhZezrq/MK9h
# DO NOT EDIT - This file is being maintained by Chef
Port <%= node[:openssh][:port] %>
+
+<% if node[:openssh][:password_authentication] -%>
+PasswordAuthentication yes
+<% else -%>
+PasswordAuthentication no
+<% end -%>
version "1.0.0"
supports "ubuntu"
-depends "chef"
# limitations under the License.
#
-include_recipe "chef"
-
-package "unzip"
package "default-jre"
cache_dir = Chef::Config[:file_cache_path]
backup false
end
-execute "#{cache_dir}/#{osmosis_package}" do
+archive_file "#{cache_dir}/#{osmosis_package}" do
action :nothing
- command "unzip -q #{cache_dir}/#{osmosis_package}"
- cwd osmosis_directory
- user "root"
+ destination osmosis_directory
+ overwrite true
+ owner "root"
group "root"
- subscribes :run, "remote_file[#{cache_dir}/#{osmosis_package}]"
+ subscribes :extract, "remote_file[#{cache_dir}/#{osmosis_package}]"
end
link "/usr/local/bin/osmosis" do
default[:osqa][:user] = "osqa"
default[:osqa][:group] = nil
+default[:osqa][:database_cluster] = "15/main"
default[:osqa][:database_name] = "osqa"
default[:osqa][:database_user] = "osqa"
default[:osqa][:database_password] = ""
default[:osqa][:sites] = []
+default[:postgresql][:versions] |= ["15"]
+
default[:accounts][:users][:osqa][:status] = :role
depends "accounts"
depends "apache"
depends "memcached"
+depends "postgresql"
depends "python"
depends "tools"
include_recipe "accounts"
include_recipe "apache"
include_recipe "memcached"
+include_recipe "postgresql"
include_recipe "python"
include_recipe "tools"
site_user = Etc.getpwuid(site_user).name if site_user.is_a?(Integer)
site_group = site[:group] || node[:osqa][:group] || Etc.getpwnam(site_user).gid
site_group = Etc.getgrgid(site_group).name if site_group.is_a?(Integer)
+ database_cluster = site[:database_cluster] || node[:osqa][:database_cluster]
database_name = site[:database_name] || node[:osqa][:database_name]
database_user = site[:database_user] || node[:osqa][:database_user]
database_password = site[:database_user] || node[:osqa][:database_password]
backup_name = site[:backup]
+ postgresql_user database_user do
+ cluster database_cluster
+ password database_password
+ end
+
+ postgresql_database database_name do
+ cluster database_cluster
+ owner database_user
+ end
+
ssl_certificate site_name do
domains [site_name] + site_aliases
notifies :reload, "service[apache2]"
line.gsub!(/^CACHE_BACKEND = .*/, "CACHE_BACKEND = 'memcached://127.0.0.1:11211/'")
line.gsub!(%r{^APP_URL = 'http://'}, "APP_URL = 'https://#{site_name}'")
line.gsub!(%r{^TIME_ZONE = 'America/New_York'}, "TIME_ZONE = 'Europe/London'")
- line.gsub!(/^DISABLED_MODULES = \[([^\]]+)\]/, "DISABLED_MODULES = [\\1, 'localauth', 'facebookauth', 'oauthauth']")
+ line.gsub!(/^DISABLED_MODULES = \[([^\]]+)\]/, "DISABLED_MODULES = [\\1, 'localauth', 'facebookauth', 'oauthauth', 'mysqlfulltext']")
line
end
<% end -%>
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
RedirectPermanent / https://<%= @name %>/
SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
DocumentRoot <%= @directory %>/osqa
WSGIScriptAlias / <%= @directory %>/osqa/osqa.wsgi
WSGIProcessGroup <%= @name %>
+
+ # Site is now closed. Block access to login page and other pages.
+ <Location /account>
+ Require all denied
+ ErrorDocument 403 "help.openstreetmap.org is closed. Use community.openstreetmap.org instead."
+ </Location>
+ <Location /questions/ask/>
+ Require all denied
+ ErrorDocument 403 "help.openstreetmap.org is closed. Use community.openstreetmap.org instead."
+ </Location>
+ <Location /contact/>
+ Require all denied
+ ErrorDocument 403 "help.openstreetmap.org is closed. Use community.openstreetmap.org instead."
+ </Location>
+ <Location /search/>
+ Require all denied
+ ErrorDocument 403 "help.openstreetmap.org is closed. Use community.openstreetmap.org instead."
+ </Location>
+ RewriteEngine on
+ RewriteCond %{REQUEST_METHOD} POST
+ RewriteRule ^/questions - [F,NC]
</VirtualHost>
<Directory <%= @directory %>/osqa>
-default[:otrs][:version] = "6.0.30"
+default[:otrs][:version] = "6.0.48"
default[:otrs][:user] = "otrs"
default[:otrs][:group] = nil
-default[:otrs][:database_cluster] = "13/main"
+default[:otrs][:database_cluster] = "15/main"
default[:otrs][:database_name] = "otrs"
default[:otrs][:database_user] = "otrs"
default[:otrs][:database_password] = "otrs"
default[:otrs][:site] = "otrs"
-default[:postgresql][:versions] |= ["13"]
+default[:postgresql][:versions] |= ["15"]
default[:accounts][:users][:otrs][:status] = :role
default[:accounts][:groups][:"www-data"][:members] = [:otrs]
depends "accounts"
depends "apache"
depends "chef"
+depends "exim"
depends "postgresql"
depends "tools"
include_recipe "accounts"
include_recipe "apache"
+include_recipe "exim"
include_recipe "postgresql"
include_recipe "tools"
passwords = data_bag_item("otrs", "passwords")
-package "libapache2-mod-perl2"
-package "libapache2-reload-perl"
-
package %w[
+ tar
+ bzip2
+ libapache-dbi-perl
+ libapache2-reload-perl
+ libarchive-zip-perl
+ libauthen-ntlm-perl
+ libauthen-sasl-perl
libcrypt-eksblowfish-perl
+ libcss-minifier-xs-perl
libdatetime-perl
+ libdbd-mysql-perl
+ libencode-hanextra-perl
+ libexcel-writer-xlsx-perl
libgd-gd2-perl
libgd-graph-perl
libgd-text-perl
+ libhtml-parser-perl
+ libio-socket-ssl-perl
+ libjavascript-minifier-xs-perl
+ libjson-perl
libjson-xs-perl
+ liblocale-codes-perl
libmail-imapclient-perl
+ libmoo-perl
+ libnet-dns-perl
libnet-ldap-perl
libpdf-api2-perl
+ libsisimai-perl
libsoap-lite-perl
+ libspreadsheet-xlsx-perl
libtemplate-perl
+ libtext-csv-xs-perl
+ libtext-diff-perl
+ libtimedate-perl
+ libxml-libxml-perl
+ libxml-libxml-simple-perl
+ libxml-libxslt-perl
+ libxml-parser-perl
+ libxml-simple-perl
libyaml-libyaml-perl
+ libyaml-perl
]
+apache_module "perl" do
+ package "libapache2-mod-perl2"
+end
+
+apache_module "deflate"
apache_module "headers"
+apache_module "rewrite"
version = node[:otrs][:version]
user = node[:otrs][:user]
owner database_user
end
-remote_file "#{Chef::Config[:file_cache_path]}/otrs-#{version}.tar.bz2" do
- source "https://download.znuny.org/releases/otrs-#{version}.tar.bz2"
- not_if { ::File.exist?("/opt/otrs-#{version}") }
+remote_file "#{Chef::Config[:file_cache_path]}/znuny-#{version}.tar.bz2" do
+ source "https://download.znuny.org/releases/znuny-#{version}.tar.bz2"
+ not_if { ::File.exist?("/opt/znuny-#{version}") }
end
-execute "untar-otrs-#{version}" do
- command "tar jxf #{Chef::Config[:file_cache_path]}/otrs-#{version}.tar.bz2"
+execute "untar-znuny-#{version}" do
+ command "tar jxf #{Chef::Config[:file_cache_path]}/znuny-#{version}.tar.bz2"
cwd "/opt"
user "root"
group "root"
- not_if { ::File.exist?("/opt/otrs-#{version}") }
+ not_if { ::File.exist?("/opt/znuny-#{version}") }
end
-config = edit_file "/opt/otrs-#{version}/Kernel/Config.pm.dist" do |line|
+config = edit_file "/opt/znuny-#{version}/Kernel/Config.pm.dist" do |line|
line.gsub!(/^( *)\$Self->{Database} = 'otrs'/, "\\1$Self->{Database} = '#{database_name}'")
line.gsub!(/^( *)\$Self->{DatabaseUser} = 'otrs'/, "\\1$Self->{DatabaseUser} = '#{database_user}'")
line.gsub!(/^( *)\$Self->{DatabasePw} = 'some-pass'/, "\\1$Self->{DatabasePw} = '#{database_password}'")
line
end
-file "/opt/otrs-#{version}/Kernel/Config.pm" do
+file "/opt/znuny-#{version}/Kernel/Config.pm" do
owner user
group "www-data"
mode "664"
content config
+ notifies :restart, "service[otrs]"
end
-link "/opt/otrs" do
- to "/opt/otrs-#{version}"
-end
-
-execute "/opt/otrs/bin/otrs.SetPermissions.pl" do
- action :run
- command "/opt/otrs/bin/otrs.SetPermissions.pl --otrs-user=#{user} --web-group=www-data /opt/otrs-#{version}"
+execute "/opt/znuny-#{version}/bin/otrs.SetPermissions.pl" do
+ action :nothing
+ command "/opt/znuny-#{version}/bin/otrs.SetPermissions.pl --otrs-user=#{user} --web-group=www-data /opt/znuny-#{version}"
user "root"
group "root"
- only_if { File.stat("/opt/otrs/README.md").uid != Etc.getpwnam("otrs").uid }
+ subscribes :run, "execute[untar-znuny-#{version}]"
end
-execute "/opt/otrs/bin/Cron.sh" do
- action :nothing
- command "/opt/otrs/bin/Cron.sh restart"
+link "/opt/otrs" do
+ to "/opt/znuny-#{version}"
+end
+
+systemd_service "otrs" do
+ description "OTRS Daemon"
+ type "forking"
user "otrs"
group "otrs"
+ exec_start "/opt/otrs/bin/otrs.Daemon.pl start"
+ private_tmp true
+ protect_system "strict"
+ protect_home true
+ read_write_paths ["/opt/znuny-#{version}/var", "/var/log/exim4", "/var/spool/exim4"]
end
-Dir.glob("/opt/otrs/var/cron/*.dist") do |distname|
- name = distname.sub(".dist", "")
-
- file name do
- owner "otrs"
- group "www-data"
- mode "664"
- content IO.read(distname)
- notifies :run, "execute[/opt/otrs/bin/Cron.sh]"
- end
+service "otrs" do
+ action [:enable, :start]
+ subscribes :restart, "link[/opt/otrs]"
+ subscribes :restart, "systemd_service[otrs]"
end
ssl_certificate site do
variables :aliases => site_aliases
end
-template "/etc/sudoers.d/otrs" do
- source "sudoers.erb"
- owner "root"
- group "root"
- mode "440"
-end
-
template "/etc/cron.daily/otrs-backup" do
source "backup.cron.erb"
owner "root"
<% end -%>
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
RedirectPermanent / https://<%= @name %>/
ServerName <%= @name %>
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
SSLEngine on
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-# Allow exim to deliver mail into OTRS
-Debian-exim ALL=(otrs) NOPASSWD: /usr/share/otrs/bin/PostMaster.pl
--- /dev/null
+# Overpass Cookbook
+
+This cookbook installs and configures an Overpass API. It can be configured
+to install a stripped down version that can only be used to serve requests
+from the "Query Feature" of the main OSM website.
--- /dev/null
+default[:overpass][:fqdn] = "overpass.openstreetmap.org"
+default[:overpass][:version] = "0.7.61.8"
+# One of: no, meta, attic
+default[:overpass][:meta_mode] = "attic"
+# One of: no, gz, lz4
+default[:overpass][:compression_mode] = "lz4"
+default[:overpass][:rate_limit] = 2
+default[:overpass][:dispatcher_space] = 10 * 1024 * 1024 * 1024
+default[:overpass][:clone_url] = "http://dev.overpass-api.de/api_drolbr"
+default[:overpass][:replication_url] = "https://planet.openstreetmap.org/replication/minute/"
+# If true only provide an API for the query feature on the website
+default[:overpass][:restricted_api] = true
+
+default[:overpass][:logdir] = "/var/log/overpass"
+
+default[:accounts][:users][:overpass][:status] = :role
-name "squid"
+name "overpass"
maintainer "OpenStreetMap Administrators"
maintainer_email "admins@openstreetmap.org"
license "Apache-2.0"
-description "Installs and configures squid"
+description "Installs and configures an Overpass server"
version "1.0.0"
supports "ubuntu"
-depends "apt"
-depends "munin"
+depends "accounts"
+depends "apache"
depends "prometheus"
+depends "ruby"
depends "systemd"
--- /dev/null
+#
+# Cookbook:: overpass
+# Recipe:: default
+#
+# Copyright:: 2021, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "accounts"
+include_recipe "apache"
+include_recipe "prometheus"
+include_recipe "ruby"
+
+username = "overpass"
+basedir = data_bag_item("accounts", username)["home"]
+web_passwords = data_bag_item("web", "passwords")
+
+%w[bin site diffs db src].each do |dirname|
+ directory "#{basedir}/#{dirname}" do
+ owner username
+ group username
+ mode "755"
+ recursive true
+ end
+end
+
+## Install overpass from source
+
+srcdir = "#{basedir}/src/osm-3s_v#{node[:overpass][:version]}"
+
+package %w[
+ build-essential
+ libexpat1-dev
+ zlib1g-dev
+ liblz4-dev
+ pyosmium
+ osmium-tool
+]
+
+remote_file "#{srcdir}.tar.gz" do
+ action :create
+ source "https://dev.overpass-api.de/releases/osm-3s_v#{node[:overpass][:version]}.tar.gz"
+ owner username
+ group username
+ mode "644"
+end
+
+execute "source_tarball" do
+ cwd "#{basedir}/src"
+ command "tar -xf #{srcdir}.tar.gz"
+ user username
+ notifies :run, "execute[install_overpass]"
+ not_if { ::File.exist?(srcdir) }
+end
+
+execute "install_overpass" do
+ action :nothing
+ user username
+ cwd srcdir
+ command "./configure --enable-lz4 --prefix=#{basedir} && make install"
+ notifies :restart, "service[overpass-dispatcher]"
+ notifies :restart, "service[overpass-area-dispatcher]"
+end
+
+## Setup Apache
+
+gem_package "rotp" do
+ gem_binary node[:ruby][:gem]
+end
+
+directory "#{basedir}/apache" do
+ owner "root"
+ group "root"
+ mode "755"
+end
+
+template "#{basedir}/apache/totp-filter" do
+ source "totp-filter.erb"
+ owner "root"
+ group "root"
+ mode "755"
+ variables :totp_key => web_passwords["totp_key"]
+end
+
+ssl_certificate node[:fqdn] do
+ domains [node[:fqdn],
+ node[:overpass][:fqdn]]
+ notifies :reload, "service[apache2]"
+end
+
+apache_module "cgi"
+apache_module "headers"
+apache_module "rewrite"
+
+apache_site "default" do
+ action :disable
+end
+
+apache_site "#{node[:overpass][:fqdn]}" do
+ template "apache.erb"
+ directory "#{basedir}/site"
+ variables :script_directory => "#{basedir}/cgi-bin"
+end
+
+## Overpass deamons
+
+meta_map_short = {
+ "no" => "",
+ "meta" => "--meta",
+ "attic" => "--attic"
+}
+
+logdir = node[:overpass][:logdir]
+
+directory logdir do
+ owner username
+ group username
+ mode "755"
+ recursive true
+end
+
+%w[overpass-update-db overpass-update-areas].each do |fname|
+ template "#{basedir}/bin/#{fname}" do
+ source "#{fname}.erb"
+ owner "overpass"
+ group "overpass"
+ mode "700"
+ variables :basedir => basedir, :srcdir => srcdir
+ end
+end
+
+template "#{basedir}/bin/overpass-import-db" do
+ source "overpass-import-db.erb"
+ owner "root"
+ group "root"
+ mode "755"
+ variables :basedir => basedir, :username => username, :srcdir => srcdir
+end
+
+systemd_service "overpass-dispatcher" do
+ description "Overpass Main Dispatcher"
+ wants ["overpass-area-dispatcher.service"]
+ working_directory basedir
+ exec_start "#{basedir}/bin/dispatcher --osm-base #{meta_map_short[node[:overpass][:meta_mode]]} --db-dir=#{basedir}/db --rate-limit=#{node[:overpass][:rate_limit]} --space=#{node[:overpass][:dispatcher_space]}"
+ exec_stop "#{basedir}/bin/dispatcher --osm-base --terminate"
+ standard_output "append:#{logdir}/osm_base.log"
+ user username
+end
+
+service "overpass-dispatcher" do
+ action [:enable]
+end
+
+systemd_service "overpass-area-dispatcher" do
+ description "Overpass Area Dispatcher"
+ after ["overpass-dispatcher.service"]
+ working_directory basedir
+ exec_start "#{basedir}/bin/dispatcher --areas #{meta_map_short[node[:overpass][:meta_mode]]} --db-dir=#{basedir}/db"
+ exec_stop "#{basedir}/bin/dispatcher --areas --terminate"
+ standard_output "append:#{logdir}/areas.log"
+ user username
+end
+
+service "overpass-area-dispatcher" do
+ action [:enable]
+end
+
+systemd_service "overpass-update" do
+ description "Overpass Update Application"
+ after ["overpass-dispatcher.service"]
+ wants ["overpass-area-processor.service"]
+ working_directory basedir
+ exec_start "#{basedir}/bin/overpass-update-db"
+ standard_output "append:#{logdir}/update.log"
+ user username
+ restart "on-success"
+end
+
+if node[:overpass][:meta_mode] == "attic"
+ systemd_service "overpass-area-processor" do
+ description "Overpass Area Processor"
+ after ["overpass-area-dispatcher.service", "overpass-update.service"]
+ working_directory basedir
+ exec_start "#{basedir}/bin/overpass-update-areas"
+ standard_output "append:#{logdir}/area-processor.log"
+ restart "on-success"
+ nice 19
+ user username
+ end
+else
+ systemd_service "overpass-area-processor" do
+ description "Overpass Area Processor"
+ after ["overpass-area-dispatcher.service", "overpass-update.service"]
+ working_directory basedir
+ exec_start "#{basedir}/bin/osm3s_query --progress --rules"
+ standard_input "file:#{srcdir}/rules/areas.osm3s"
+ standard_output "append:#{logdir}/area-processor.log"
+ restart "on-success"
+ nice 19
+ user username
+ end
+end
+
+systemd_timer "overpass-area-processor" do
+ action :delete
+end
+
+service "overpass-area-processor" do
+ action [:disable]
+end
+
+template "/etc/logrotate.d/overpass" do
+ source "logrotate.erb"
+ owner "root"
+ group "root"
+ mode "644"
+ variables :logdir => logdir
+end
+
+prometheus_exporter "overpass" do
+ port 9898
+ user username
+ restrict_address_families "AF_UNIX"
+ options [
+ "--overpass.base-directory=#{basedir}"
+ ]
+end
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+<VirtualHost *:80>
+ ServerName <%= node[:fqdn] %>
+ ServerAlias <%= node[:overpass][:fqdn] %>
+ ServerAdmin webmaster@openstreetmap.org
+
+ CustomLog /var/log/apache2/<%= node[:overpass][:fqdn] %>-access.log combined_extended
+ ErrorLog /var/log/apache2/<%= node[:overpass][:fqdn] %>-error.log
+
+ DocumentRoot <%= @directory %>
+
+ RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
+ RedirectPermanent / https://<%= @name %>/
+</VirtualHost>
+
+
+<VirtualHost *:443>
+ ServerName <%= node[:fqdn] %>
+ ServerAlias <%= node[:overpass][:fqdn] %>
+ ServerAdmin webmaster@openstreetmap.org
+
+ CustomLog /var/log/apache2/<%= node[:overpass][:fqdn] %>-access.log combined_extended
+ ErrorLog /var/log/apache2/<%= node[:overpass][:fqdn] %>-error.log
+
+ SSLEngine on
+ SSLCertificateFile /etc/ssl/certs/<%= node[:fqdn] %>.pem
+ SSLCertificateKeyFile /etc/ssl/private/<%= node[:fqdn] %>.key
+
+ DocumentRoot <%= @directory %>
+
+ RewriteEngine on
+ RewriteMap totp prg:/srv/query.openstreetmap.org/apache/totp-filter
+ RewriteCond ${totp:%{HTTP_COOKIE}} =0
+ RewriteRule ^/query-features - [F,L]
+
+<% if node[:overpass][:restricted_api] -%>
+ ScriptAlias /query-features <%= @script_directory %>/interpreter
+ SetEnvIf Origin "http.*(osm.org|openstreetmap.org).*" AccessControlAllowOrigin=$0
+ # Remove Origin so Overpass does not interfere.
+ RequestHeader unset Origin
+ Header always add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
+ Header always add Access-Control-Allow-Credentials true
+<% else -%>
+ ScriptAlias /api/ <%= @script_directory %>/
+<% end -%>
+</VirtualHost>
+
+<Directory "<%= @directory %>">
+ Require all granted
+</Directory>
+
+<Directory "<%= @script_directory %>">
+ SetOutputFilter DEFLATE
+
+ AllowOverride None
+ Options +ExecCGI -MultiViews +FollowSymLinks
+ Require all granted
+</Directory>
# DO NOT EDIT - This file is being maintained by Chef
-[if_<%= @ifname %>]
-env.speed 1000
+<%= @logdir %>/*.log {
+ missingok
+ compress
+}
--- /dev/null
+#!/bin/bash -e
+
+FNAME=$1
+
+if [[ "x$FNAME" == "x" ]]; then
+ echo "Usage: overpass-import-db <OSM file>"
+ exit 1
+fi
+
+case "$FNAME" in
+ *.gz) UNPACKER='gunzip -c' ;;
+ *.bz2) UNPACKER='bunzip2 -c' ;;
+ *) UNPACKER='osmium cat -o - -f xml' ;;
+esac
+
+<% if node[:overpass][:meta_mode] == "meta" -%>
+META=--meta
+<% elsif node[:overpass][:meta_mode] == "attic" -%>
+META=--keep-attic
+<% else -%>
+META=
+<% end -%>
+
+sudo systemctl stop overpass-area-processor || true
+sudo systemctl stop overpass-update || true
+sudo systemctl stop overpass-area-dispatcher || true
+sudo systemctl stop overpass-dispatcher || true
+
+sleep 2
+
+# Remove old database
+sudo -u <%= @username %> rm -rf <%= @basedir %>/db/*
+
+$UNPACKER $FNAME | sudo -u <%= @username %> <%= @basedir %>/bin/update_database --db-dir='<%= @basedir %>/db' --compression-method=<%= node[:overpass][:compression_mode] %> --map-compression-method=<%= node[:overpass][:compression_mode] %> $META
+
+sudo -u <%= @username %> ln -s <%= @srcdir %>/rules <%= @basedir %>/db/rules
+
+echo "Import finished. Catching up with new changes."
+
+sudo systemctl start overpass-dispatcher
+sudo systemctl start overpass-area-dispatcher
+
+PYOSMIUM="sudo -u <%= @username %> pyosmium-get-changes --server <%= node[:overpass][:replication_url] %> -f <%= @basedir %>/db/replicate-id"
+<% if node[:overpass][:meta_mode] == "attic" -%>
+PYOSMIUM="$PYOSMIUM --no-deduplicate"
+<% end -%>
+
+# Get the replication id
+$PYOSMIUM -v -O $FNAME --ignore-osmosis-headers
+
+sudo -u <%= @username %> rm -f <%= @basedir %>/diffs/*
+
+while $PYOSMIUM -v -s 1000 -o <%= @basedir %>/diffs/latest.osc; do
+ if [ ! -f <%= @basedir %>/db/replicate-id ]; then
+ echo "Replication ID not written."
+ exit 1
+ fi
+ DATA_VERSION=`osmium fileinfo -e -g data.timestamp.last <%= @basedir %>/diffs/latest.osc`
+ echo "Downloaded up to timestamp $DATA_VERSION"
+ while ! sudo -u <%= @username %> <%= @basedir %>/bin/update_from_dir --osc-dir=<%= @basedir %>/diffs --version=$DATA_VERSION $META --flush-size=0; do
+ echo "Error while updating. Retry in 1 min."
+ sleep 60
+ done
+ sudo -u <%= @username %> rm <%= @basedir %>/diffs/latest.osc
+ echo "Finished up to $DATA_VERSION."
+done
+
+echo "DB up-to-date. Processing areas."
+
+sudo -u <%= @username %> <%= @basedir %>/bin/osm3s_query --progress --rules <<%= @srcdir %>/rules/areas.osm3s
+
+echo "All updates done."
--- /dev/null
+#!/bin/bash
+
+echo "`date '+%F %T'`: update started"
+
+if [[ -a <%= @basedir %>/db/area_version ]]; then
+ sed "s/{{area_version}}/$(cat <%= @basedir %>/db/area_version)/g" <%= @srcdir %>/rules/areas_delta.osm3s | <%= @basedir %>/bin/osm3s_query --progress --rules
+else
+ cat <%= @srcdir %>/rules/areas.osm3s | <%= @basedir %>/bin/osm3s_query --progress --rules
+fi
+
+echo "`date '+%F %T'`: update finished"
--- /dev/null
+#!/bin/bash
+
+PYOSMIUM="pyosmium-get-changes --server <%= node[:overpass][:replication_url] %> -f <%= @basedir %>/db/replicate-id"
+<% if node[:overpass][:meta_mode] == "attic" -%>
+PYOSMIUM="$PYOSMIUM --no-deduplicate"
+<% end -%>
+
+<% if node[:overpass][:meta_mode] == "meta" -%>
+META=--meta
+<% elsif node[:overpass][:meta_mode] == "attic" -%>
+META=--keep-attic
+<% else -%>
+META=
+<% end -%>
+
+status=3 # make it sleep on issues
+
+if [ -f <%= @basedir %>/db/replicate-id ]; then
+ # first apply any pending updates
+ if [ -f <%= @basedir %>/diffs/latest.osc ]; then
+ DATA_VERSION=`osmium fileinfo -e -g data.timestamp.last <%= @basedir %>/diffs/latest.osc`
+ if [ "x$DATA_VERSION" != "x" ]; then
+ echo "Downloaded up to timestamp $DATA_VERSION"
+ while ! <%= @basedir %>/bin/update_from_dir --osc-dir=<%= @basedir %>/diffs --version=$DATA_VERSION $META --flush-size=0; do
+ echo "Error while updating. Retry in 1 min."
+ sleep 60
+ done
+ fi
+ rm <%= @basedir %>/diffs/latest.osc
+ fi
+
+ $PYOSMIUM -v -s 1000 -o <%= @basedir %>/diffs/latest.osc
+ status=$?
+fi
+
+if [ $status -eq 0 ]; then
+ echo "Downloaded next batch."
+elif [ $status -eq 3 ]; then
+ rm <%= @basedir %>/diffs/latest.osc
+ echo "No new data, sleeping for a minute."
+ sleep 60
+else
+ echo "Fatal error, stopping updates."
+ exit $status
+fi
--- /dev/null
+#!/usr/bin/ruby
+
+require "cgi"
+require "rotp"
+
+totp = ROTP::TOTP.new("<%= @totp_key %>", :interval => 3600)
+
+STDIN.each_line do |header|
+ cookies = CGI::Cookie.parse(header.chomp)
+
+ if cookie = cookies.fetch("_osm_totp_token", nil)
+ if totp.verify(cookie.value.first, :drift_behind => 3600, :drift_ahead => 3600)
+ STDOUT.syswrite("1\n")
+ else
+ STDOUT.syswrite("0\n")
+ end
+ else
+ STDOUT.syswrite("0\n")
+ end
+end
+
+exit 0
--- /dev/null
+# oxidized cookbook
+
+This cookbook installs and configures [oxidized](https://github.com/ytti/oxidized) to
+backup the configurations of OpenStreetMap equipment.
--- /dev/null
+default[:accounts][:users][:oxidized][:status] = :role
-name "donate"
+name "oxidized"
maintainer "OpenStreetMap Administrators"
maintainer_email "admins@openstreetmap.org"
license "Apache-2.0"
-description "Installs and configures Donate Site"
+description "Configures oxidized to backup equipment configuration"
version "1.0.0"
supports "ubuntu"
depends "accounts"
-depends "apache"
depends "git"
-depends "mysql"
-depends "php"
+depends "ruby"
--- /dev/null
+#
+# Cookbook:: oxidized
+# Recipe:: default
+#
+# Copyright:: 2022, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "git"
+include_recipe "ruby"
+
+package %w[
+ gcc
+ g++
+ make
+ cmake
+ libssl-dev
+ libssh2-1-dev
+ zlib1g-dev
+ pkg-config
+ libyaml-dev
+]
+
+keys = data_bag_item("oxidized", "keys")
+devices = data_bag_item("oxidized", "devices")
+
+directory "/etc/oxidized" do
+ owner "root"
+ group "root"
+ mode "755"
+end
+
+template "/etc/oxidized/config" do
+ source "config.erb"
+ owner "oxidized"
+ group "oxidized"
+ mode "444"
+ notifies :restart, "service[oxidized]"
+end
+
+template "/etc/oxidized/routers.db" do
+ source "routers.db.erb"
+ owner "oxidized"
+ group "oxidized"
+ mode "400"
+ variables :devices => devices
+ notifies :restart, "service[oxidized]"
+end
+
+directory "/var/log/oxidized" do
+ owner "oxidized"
+ group "oxidized"
+ mode "755"
+end
+
+directory "/opt/oxidized" do
+ owner "oxidized"
+ group "oxidized"
+ mode "755"
+end
+
+git "/opt/oxidized/daemon" do
+ action :sync
+ repository "https://github.com/openstreetmap/oxidized.git"
+ depth 1
+ user "oxidized"
+ group "oxidized"
+ notifies :run, "bundle_install[/opt/oxidized/daemon]", :immediately
+end
+
+directory "/opt/oxidized/.ssh" do
+ owner "oxidized"
+ group "oxidized"
+ mode "700"
+end
+
+# Key is set as a deployment key in github repo
+file "/opt/oxidized/.ssh/id_ed25519" do
+ content keys["git"].join("\n")
+ owner "oxidized"
+ group "oxidized"
+ mode "400"
+ notifies :delete, "file[/opt/oxidized/.ssh/id_ed25519.pub]", :immediately
+ notifies :restart, "service[oxidized]"
+end
+
+# Ensure public key is deleted if private key is changed. Trigged by notify
+file "/opt/oxidized/.ssh/id_ed25519.pub" do
+ action :nothing
+end
+
+execute "/opt/oxidized/.ssh/id_ed25519.pub" do
+ command "ssh-keygen -f /opt/oxidized/.ssh/id_ed25519 -y > /opt/oxidized/.ssh/id_ed25519.pub"
+ user "oxidized"
+ group "oxidized"
+ creates "/opt/oxidized/.ssh/id_ed25519.pub"
+ notifies :restart, "service[oxidized]"
+end
+
+ssh_known_hosts_entry "github.com" do
+ action [:create, :flush]
+ file_location "/opt/oxidized/.ssh/known_hosts"
+ owner "oxidized"
+ group "oxidized"
+end
+
+directory "/var/lib/oxidized" do
+ owner "oxidized"
+ group "oxidized"
+ mode "750"
+end
+
+git "/var/lib/oxidized/configs.git" do
+ action :sync
+ repository "git@github.com:openstreetmap/oxidized-configs.git" # Uses oxidized ssh key
+ checkout_branch "master" # branch is hardcoded in oxidized
+ user "oxidized"
+ group "oxidized"
+end
+
+bundle_install "/opt/oxidized/daemon" do
+ action :nothing
+ options "--deployment"
+ user "oxidized"
+ group "oxidized"
+ notifies :restart, "service[oxidized]"
+end
+
+# Based on https://github.com/ytti/oxidized/blob/master/extra/oxidized.service
+systemd_service "oxidized" do
+ description "oxidized network device backup daemon"
+ after "network.target"
+ user "oxidized"
+ working_directory "/opt/oxidized/daemon"
+ runtime_directory "oxidized"
+ exec_start "#{node[:ruby][:bundle]} exec oxidized"
+ environment "OXIDIZED_HOME" => "/etc/oxidized",
+ "OXIDIZED_LOGS" => "/var/log/oxidized"
+ nice 10
+ sandbox :enable_network => true
+ read_write_paths ["/run/oxidized", "/var/lib/oxidized", "/var/log/oxidized"]
+ restart "on-failure"
+ notifies :restart, "service[oxidized]"
+end
+
+service "oxidized" do
+ action [:enable, :start]
+end
+
+template "/etc/logrotate.d/oxidized" do
+ source "logrotate.erb"
+ owner "root"
+ group "root"
+ mode "644"
+end
--- /dev/null
+---
+# DO NOT EDIT - This file is being maintained by Chef
+rest: false
+timeout: 60
+vars:
+ remove_secret: true
+pid: "/run/oxidized/oxidized.pid"
+crash:
+ directory: /var/lib/oxidized/crashes
+input:
+ default: ssh
+output:
+ default: git
+ git:
+ single_repo: true
+ user: oxidized
+ email: oxidized@openstreetmap.org
+ repo: "/var/lib/oxidized/configs.git"
+hooks:
+ push_to_remote:
+ type: githubrepo
+ events: [post_store]
+ remote_repo: git@github.com:openstreetmap/oxidized-configs.git
+ privatekey: /opt/oxidized/.ssh/id_ed25519
+source:
+ default: csv
+ csv:
+ file: "/etc/oxidized/routers.db"
+ delimiter: !ruby/regexp /:/
+ map:
+ name: 0
+ model: 1
+ input: 2
+ username: 3
+ password: 4
+model_map:
+ juniper: junos
+ apc: apc_aos
+ ciscocmb: ciscosmb
# DO NOT EDIT - This file is being maintained by Chef
-/var/log/<%= @name %>-init.log {
+/var/log/oxidized/*.log {
+ rotate 12
weekly
- rotate 4
+ size 10M
compress
delaycompress
missingok
- create 0640 root adm
}
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+<% @devices[:hardware].keys.sort.each do |d| -%>
+<%= d -%>:<%= @devices[:hardware][d][:device] -%>:<%= @devices[:hardware][d][:input] -%>:<%= @devices[:hardware][d][:username] -%>:<%= @devices[:hardware][d][:password] %>
+<% end -%>
-default[:passenger][:ruby_version] = if node[:lsb][:release].to_f < 20.04
- "2.5"
- else
- "2.7"
- end
-
default[:passenger][:max_pool_size] = 6
default[:passenger][:pool_idle_time] = 300
-default[:passenger][:instance_registry_dir] = "/run/passenger"
-
-default[:apt][:sources] = node[:apt][:sources] | ["passenger"]
+default[:passenger][:instance_registry_dir] = "/run/passenger-instreg"
supports "ubuntu"
depends "apache"
depends "apt"
-depends "munin"
depends "prometheus"
+depends "ruby"
depends "systemd"
#
include_recipe "apache"
-include_recipe "apt"
-include_recipe "munin"
+include_recipe "apt::passenger"
include_recipe "prometheus"
-
-package "ruby#{node[:passenger][:ruby_version]}"
-package "ruby#{node[:passenger][:ruby_version]}-dev"
-
-if node[:passenger][:ruby_version].to_f < 1.9
- package "rubygems#{node[:passenger][:ruby_version]}"
- package "irb#{node[:passenger][:ruby_version]}"
-end
+include_recipe "ruby"
template "/usr/local/bin/passenger-ruby" do
source "ruby.erb"
conf "passenger.conf.erb"
end
-munin_plugin_conf "passenger" do
- template "munin.erb"
-end
-
-munin_plugin "passenger_memory"
-munin_plugin "passenger_processes"
-munin_plugin "passenger_queues"
-munin_plugin "passenger_requests"
-
prometheus_exporter "passenger" do
port 9149
+ user "root"
environment "PASSENGER_INSTANCE_REGISTRY_DIR" => node[:passenger][:instance_registry_dir]
+ options "--passenger.command.timeout-seconds=5"
+ restrict_address_families "AF_UNIX"
end
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-[passenger_*]
-user root
-env.PASSENGER_INSTANCE_REGISTRY_DIR <%= node[:passenger][:instance_registry_dir] %>
PassengerMaxPoolSize <%= node[:passenger][:max_pool_size] %>
PassengerPoolIdleTime <%= node[:passenger][:pool_idle_time] %>
PassengerFriendlyErrorPages off
- PassengerInstanceRegistryDir /run/passenger
+ PassengerInstanceRegistryDir <%= node[:passenger][:instance_registry_dir] %>
</IfModule>
#!/bin/sh
-<% if node[:passenger][:ruby_version].to_f < 2.1 -%>
-export RUBY_HEAP_MIN_SLOTS=500000
-export RUBY_HEAP_FREE_MIN=100000
-<% else -%>
export RUBY_GC_HEAP_INIT_SLOTS=500000
export RUBY_GC_HEAP_FREE_SLOTS=100000
-<% end -%>
export RUBY_GC_MALLOC_LIMIT=50000000
-exec /usr/bin/ruby<%= node[:passenger][:ruby_version] %> "$@"
+exec /usr/bin/ruby<%= node[:ruby][:version] %> "$@"
-default[:php][:version] = if node[:lsb][:release].to_f < 20.04
- "7.2"
- else
+default[:php][:version] = if platform?("debian")
+ "8.2"
+ elsif node[:lsb][:release].to_f < 22.04
"7.4"
+ else
+ "8.1"
end
-
default[:php][:fpm][:options] = {}
if new_resource.prometheus_port
prometheus_exporter "phpfpm" do
port new_resource.prometheus_port
+ restrict_address_families "AF_UNIX"
service service_name
+ group "www-data"
command "server"
- options "--phpfpm.scrape-uri=#{scrape_uri}"
+ options "--phpfpm.scrape-uri=#{scrape_uri} --phpfpm.fix-process-count"
+ labels "pool" => new_resource.pool
end
else
prometheus_exporter "phpfpm" do
if new_resource.port
"tcp://127.0.0.1:#{new_resource.port}/status"
else
- "unix:///run/php/#{new_resource.pool}.sock;/status"
+ "unix:///run/php/php-#{new_resource.pool}-fpm.sock;/status"
end
end
end
listen = 127.0.0.1:<%= @port %>
listen.backlog = 256
<% else -%>
-listen = /run/php/<%= @pool %>.sock
+listen = /run/php/php-<%= @pool %>-fpm.sock
listen.owner = www-data
listen.group = www-data
<% end -%>
+++ /dev/null
-# Piwik Cookbook
-
-This cookbook installs and configures the Piwiki server-side software used for
-analytics on openstreetmap.org
+++ /dev/null
-default[:piwik][:version] = "4.3.1"
-default[:piwik][:plugins] = %w[
- Actions Annotations API BulkTracking Contents CoreAdminHome CoreConsole
- CoreHome CorePluginsAdmin CoreUpdater CoreVisualizations CustomJsTracker
- CustomVariables Dashboard DevicePlugins DevicesDetection Diagnostics
- Ecommerce Events Feedback GeoIp2 Goals Heartbeat ImageGraph Insights
- Installation Intl LanguagesManager Live Login Marketplace MobileMessaging
- Monolog Morpheus MultiSites Overlay PagePerformance PrivacyManager
- ProfessionalServices Provider Proxy Referrers Resolution RssWidget
- ScheduledReports SegmentEditor SEO SitesManager Transitions UserCountry
- UserCountryMap UserId UserLanguage UsersManager VisitFrequency
- VisitorInterest VisitsSummary VisitTime WebsiteMeasurable Widgetize
-]
+++ /dev/null
-#
-# Cookbook:: piwik
-# Recipe:: default
-#
-# Copyright:: 2011, OpenStreetMap Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-include_recipe "apache"
-include_recipe "geoipupdate"
-include_recipe "mysql"
-include_recipe "php::fpm"
-
-passwords = data_bag_item("piwik", "passwords")
-
-package %w[
- php-cli
- php-curl
- php-mbstring
- php-mysql
- php-gd
- php-xml
- php-apcu
- unzip
-]
-
-apache_module "expires"
-apache_module "rewrite"
-
-version = node[:piwik][:version]
-
-directory "/opt/piwik-#{version}" do
- owner "root"
- group "root"
- mode "0755"
-end
-
-remote_file "#{Chef::Config[:file_cache_path]}/piwik-#{version}.zip" do
- source "https://builds.matomo.org/piwik-#{version}.zip"
- not_if { ::File.exist?("/opt/piwik-#{version}/piwik") }
-end
-
-execute "unzip-piwik-#{version}" do
- command "unzip -q #{Chef::Config[:file_cache_path]}/piwik-#{version}.zip"
- cwd "/opt/piwik-#{version}"
- user "root"
- group "root"
- not_if { ::File.exist?("/opt/piwik-#{version}/piwik") }
-end
-
-execute "/opt/piwik-#{version}/piwik/piwik.js" do
- command "gzip -k -9 /opt/piwik-#{version}/piwik/piwik.js"
- cwd "/opt/piwik-#{version}"
- user "root"
- group "root"
- not_if { ::File.exist?("/opt/piwik-#{version}/piwik/piwik.js.gz") }
-end
-
-directory "/opt/piwik-#{version}/piwik/config" do
- owner "www-data"
- group "www-data"
- mode "0755"
-end
-
-template "/opt/piwik-#{version}/piwik/config/config.ini.php" do
- source "config.erb"
- owner "root"
- group "root"
- mode "0644"
- variables :passwords => passwords,
- :directory => "/opt/piwik-#{version}/piwik",
- :plugins => node[:piwik][:plugins]
-end
-
-directory "/opt/piwik-#{version}/piwik/tmp" do
- owner "www-data"
- group "www-data"
- mode "0755"
-end
-
-link "/opt/piwik-#{version}/piwik/misc/GeoLite2-ASN.mmdb" do
- to "/usr/share/GeoIP/GeoLite2-ASN.mmdb"
-end
-
-link "/opt/piwik-#{version}/piwik/misc/GeoLite2-City.mmdb" do
- to "/usr/share/GeoIP/GeoLite2-City.mmdb"
-end
-
-link "/opt/piwik-#{version}/piwik/misc/GeoLite2-Country.mmdb" do
- to "/usr/share/GeoIP/GeoLite2-Country.mmdb"
-end
-
-link "/srv/piwik.openstreetmap.org" do
- to "/opt/piwik-#{version}/piwik"
- notifies :restart, "service[php#{node[:php][:version]}-fpm]"
-end
-
-mysql_user "piwik@localhost" do
- password passwords["database"]
-end
-
-mysql_database "piwik" do
- permissions "piwik@localhost" => :all
-end
-
-ssl_certificate "piwik.openstreetmap.org" do
- domains ["piwik.openstreetmap.org", "piwik.osm.org"]
- notifies :reload, "service[apache2]"
-end
-
-php_fpm "piwik.openstreetmap.org" do
- prometheus_port 9253
-end
-
-apache_site "piwik.openstreetmap.org" do
- template "apache.erb"
-end
-
-cron_d "piwik" do
- minute "5"
- user "www-data"
- command "/usr/bin/php /srv/piwik.openstreetmap.org/console core:archive --quiet --url=https://piwik.openstreetmap.org/"
-end
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-<VirtualHost *:443>
- ServerName piwik.openstreetmap.org
- ServerAlias piwik.osm.org
- ServerAdmin webmaster@openstreetmap.org
-
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/piwik.openstreetmap.org.pem
- SSLCertificateKeyFile /etc/ssl/private/piwik.openstreetmap.org.key
-
- CustomLog /var/log/apache2/piwik.openstreetmap.org-access.log combined
- ErrorLog /var/log/apache2/piwik.openstreetmap.org-error.log
-
- Options -Indexes
-
- DocumentRoot /srv/piwik.openstreetmap.org
-</VirtualHost>
-
-<VirtualHost *:80>
- ServerName piwik.openstreetmap.org
- ServerAlias piwik.osm.org
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/piwik.openstreetmap.org-access.log combined
- ErrorLog /var/log/apache2/piwik.openstreetmap.org-error.log
-
- RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
- RedirectPermanent / https://piwik.openstreetmap.org/
-</VirtualHost>
-
-<Directory /srv/piwik.openstreetmap.org>
- Require all granted
-
- ExpiresActive On
- RewriteEngine on
-
- RewriteCond "%{HTTP:Accept-encoding}" "gzip"
- RewriteCond "%{REQUEST_FILENAME}\.gz" -s
- RewriteRule "^(.*)\.js" "$1\.js\.gz" [QSA]
-
- RewriteRule "\.js\.gz$" "-" [T=text/javascript,E=no-gzip:1]
-
- <FilesMatch "\.js\.gz$">
- Header append Content-Encoding gzip
- Header append Vary Accept-Encoding
- </FilesMatch>
-
- <FilesMatch "(\.js|\.js\.gz)$">
- ExpiresDefault "access plus 1 week"
- Header set Cache-Control "max-age=604800"
- </FilesMatch>
-
- <FilesMatch ".+\.ph(ar|p|tml)$">
- SetHandler "proxy:unix:/run/php/piwik.openstreetmap.org.sock|fcgi://127.0.0.1"
- </FilesMatch>
-</Directory>
default[:planet][:dump][:xml_history_directory] = "/store/planet/planet/full-history"
default[:planet][:dump][:pbf_directory] = "/store/planet/pbf"
default[:planet][:dump][:pbf_history_directory] = "/store/planet/pbf/full-history"
-
-default[:planet][:current][:jobs] = {}
--- /dev/null
+#!/usr/bin/python3
+
+print( """
+<html>
+ <head>
+ <title>OpenStreetMap historical CC BY-SA 2.0 licensed data</title>
+ <link href="/style.css" rel="stylesheet" type="text/css">
+ </head>
+ <body>
+<img id="logo" src="/logo.png" alt="OSM logo" width="128" height="128">
+<h1>planet.openstreetmap.org - cc by-sa</h1>
+<p>Licensed under the <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC BY-SA 2.0</a></p>
+<p> </p>
+""")
-#!/usr/bin/env python
+#!/usr/bin/python3
-print """
+print("""
<html>
<head>
<title>OpenStreetMap historical CC BY-SA 2.0 licensed data</title>
<p>The <tt>full-planet-120401-final.osm.bz2</tt> file is the last dump of data before <a href="https://blog.osmfoundation.org/2012/07/26/automated-redactions-complete/">redactions were run to remove data which could not be released under ODbL</a>. The <tt>full-planet-120601-1150.osm.bz2</tt> is the last dump of data available under CC BY-SA, but after the redactions were run. This means it may have less data in some areas, although many redactions were quickly re-mapped.</p>
<p>Licensed under the <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC BY-SA 2.0</a></p>
<p> </p>
-"""
+""")
-#!/usr/bin/env python
+#!/usr/bin/python3
from time import time
from os import stat, environ
changesets_link = file_info('planet/changesets-latest.osm.bz2', 'planet/changesets-bz2-rss.xml', 'Latest Weekly Changesets')
planet_pbf_link = file_info('pbf/planet-latest.osm.pbf', 'pbf/planet-pbf-rss.xml', 'Latest Weekly Planet PBF File')
-print """
+print("""
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
- <title>Index of /</title>
+ <title>Planet OSM</title>
<link href="https://planet.openstreetmap.org/style.css" rel="stylesheet" type="text/css">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<img id="logo" src="https://planet.openstreetmap.org/logo.png" alt="OSM logo" width="128" height="128">
<h1>Planet OSM</h1>
<p>
-The files found here are regularly-updated, complete copies of the OpenStreetMap.org
-database, and those published before the 12 September 2012 are distributed under a Creative Commons Attribution-ShareAlike 2.0 license, those published after are Open Data Commons Open Database License 1.0 licensed. For more information, <a href="https://wiki.openstreetmap.org/wiki/Planet.osm">see the project wiki</a>.
+The files found here are regularly-updated, complete copies of the <a href="https://openstreetmap.org">OpenStreetMap</a> database.
</p>
-<p><div class="alert"><strong>WARNING</strong> Download speeds are currently restricted to 4096 KB/s due to limited available capacity on our Internet connection. <a href="https://wiki.openstreetmap.org/wiki/Planet.osm#BitTorrent">Please use torrents</a> or <a href="https://wiki.openstreetmap.org/wiki/Planet.osm#Planet.osm_mirrors">a mirror</a> if possible.</div></p>
-<table id="about">
- <tr>
- <th>
- <h2>Complete OSM Data</h2>
- </th>
- <th>
- <h2>Using The Data</h2>
- </th>
- <th>
- <h2>Extracts & Mirrors</h2>
- </th>
- </tr>
- <tr>
- <td>
- <p>%(planet_link)s</p>
- <p>%(changesets_link)s</p>
- <p>%(planet_pbf_link)s</p>
- <p>
- Each week, a new and complete copy of all data in OpenStreetMap is made
- available as both a compressed XML file and a custom PBF format file.
- Also available is the <a href="planet/full-history">'history'</a> file
- which contains not only up-to-date data but also older versions of data
- and deleted data items.
- <p>
- </p>
- A smaller file with complete metadata for all changes ('changesets') in
- XML format is also available.
- </p>
- </td>
- <td>
+<p>
+Files published before 12 September 2012 are distributed under a Creative Commons Attribution-ShareAlike 2.0 license, those
+published after are Open Data Commons Open Database License 1.0 licensed. For more information, <a href="https://wiki.openstreetmap.org/wiki/Planet.osm">see the project wiki</a>.
+</p>
+<div id="about">
+ <div>
+ <h2>Latest Exports</h2>
+ <p>%(planet_link)s</p>
+ <p>%(changesets_link)s</p>
+ <p>%(planet_pbf_link)s</p>
+ <p>
+ Each week, a new and complete copy of all data in OpenStreetMap is made
+ available as both a compressed XML file and a custom PBF format file.
+ Also available is the <a href="planet/full-history">'history'</a> file
+ which contains not only up-to-date data but also older versions of data
+ and deleted data items.
+ <p>
+ </p>
+ A smaller file with complete metadata for all changes ('changesets') in
+ XML format is also available.
+ </p>
+ </div>
+ <div>
+ <h2>Using the Data</h2>
<p>
You are granted permission to use OpenStreetMap data by
<a href="https://osm.org/copyright">the OpenStreetMap License</a>, which also describes
<a href="https://osmdata.openstreetmap.de/">Processed coastline data</a>
derived from OSM data is also needed for rendering usable maps.
</p>
- </td>
- <td>
+ <h3>Extracts & Mirrors</h3>
<p>
The complete planet is very large, so you may prefer to use one of
<a href="https://wiki.openstreetmap.org/wiki/Planet.osm#Downloading">several periodic extracts</a>
and <a href="https://download.bbbike.org/osm/">BBBike.org</a> are two providers
of extracts with up-to-date worldwide coverage.
</p>
- </td>
- </tr>
-</table>
+ </div>
+ <div>
+ <h2 id="supporting-osm">Supporting OSM</h2>
+ <p>OSM data is free to use, but is not free to make or host. The
+ stability and accuracy of OSM.org depends on its volunteers and
+ donations from its users. Please consider
+ <a href="https://supporting.openstreetmap.org">making an annual
+ recurring gift</a> to OSM to support the infrastructure,
+ tools, working groups, and other incentives needed to
+ create the map.</p>
+ <p>Donations can be made at <a href="https://supporting.openstreetmap.org/donate">supporting.openstreetmap.org/donate</a>.
+ Suggestions assume $US or equivalent.</p>
+ <ul>
+ <li>individual user, revenue < $5k/yr, $50-$100</li>
+ <li>small organization, revenue $5-10k/yr, $250-$500</li>
+ <li>medium organization, revenue $10-100k/yr, $500-$1000</li>
+ </ul>
+ <p>Large businesses with revenue in the hundreds of thousands to
+ millions should <a
+ href="https://osmfoundation.org/wiki/Join_as_a_corporate_member">join as
+ corporate members</a> to receive additional benefits.</p>
+ </div>
+</div>
<p>
If you find data within OpenStreetMap that you believe is an infringement of someone else's copyright, then please make contact with the <a href="https://wiki.openstreetmap.org/wiki/Data_working_group">OpenStreetMap Data Working Group</a>.
</p>
-""" % locals()
+<h2>Files</h2>
+""" % locals())
-#!/usr/bin/env python
+#!/usr/bin/python3
from time import time
from os import stat, environ
planet_link = file_info('history-latest.osm.bz2', 'Latest Full History Planet XML File')
planet_pbf_link = file_info('../../pbf/full-history/history-latest.osm.pbf', 'Latest Full History Planet PBF File')
-print """
+print("""
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<p>
If you find data within OpenStreetMap that you believe is an infringement of someone else's copyright, then please make contact with the <a href="https://wiki.openstreetmap.org/wiki/Data_working_group">OpenStreetMap Data Working Group</a>.
</p>
-""" % locals()
+""" % locals())
-body,
-table#about tr *
-{
+body {
font-family: sans-serif;
line-height: 1.25em;
+ margin: 2em;
+ min-width: 350px;
+ max-width: 1100px;
}
-body { margin: 2em; }
img#logo { float: left; }
img#logo, h1 { margin: 0 1em 0 0; }
-a { white-space: nowrap; }
li { margin-bottom: 1em; }
-body>p { width: 42em; }
-table#about
-{
- clear: left;
- margin: 3em 0 2em 0;
+p, li {color: #333;}
+
+#about {
+ display: flex;
+ flex-direction: row;
+ width: 100%;
+}
+
+#about > div {
+ padding-right: 2em;
+ flex: 1;
+}
+
+@media(max-width: 900px) {
+ body {
+ margin: 20px 10px;
+ }
+
+ img#logo {
+ width: 64px;
+ height: 64px;
+ }
+
+ #about {
+ flex-direction: column;
+ }
+
+ #about > div {
+ padding-right: 0;
+ }
+
+ pre {
+ width: 100%;
+ overflow: scroll;
+ }
+}
+
+ul {
+ padding-left: 1em;
+}
+
+ul li {
+ margin-bottom: 0.3em;
}
table tr th { text-align: left; }
}
.alert {
+ clear: both;
padding: 20px;
background-color: #ff9800; /* Orange */
color: white;
- margin-bottom: 15px;
+ margin: 15px auto;
+ max-width: 42em;
+ border-radius: 4px;
}
# to guarantee sync for newly created directories.
def fdirsync(d)
while d != "/"
- Dir.open(d) do |dh|
- io = IO.for_fd(dh.fileno)
- io.fsync
- end
+ fsync(d)
d = File.dirname(d)
end
end
@config["data_dir"] + format("/%03d/%03d/%03d", sequence / 1000000, (sequence / 1000) % 1000, (sequence % 1000))
end
+ def s3_stem
+ @config["s3_dir"] + format("/%03d/%03d/%03d", sequence / 1000000, (sequence / 1000) % 1000, (sequence % 1000))
+ end
+
def write_tmp_files!(changesets)
data_file = data_stem + ".osm.gz"
tmp_state = @config["state_file"] + ".tmp"
Zlib::GzipWriter.open(tmp_data) do |fh|
fh.write(changeset_dump(changesets))
end
- File.open(tmp_state, "w") do |fh|
- fh.write(YAML.dump(@state))
- end
+ File.write(tmp_state, YAML.dump(@state))
# fsync the files in their old locations.
fsync(tmp_data)
# from the dirent and has been updated to account for any allocations.
fdirsync(File.dirname(data_file))
fdirsync(File.dirname(@config["state_file"]))
+
+ if @config["s3_dir"]
+ s3_file = s3_stem + ".osm.gz"
+ s3_state_file = s3_stem + ".state.txt"
+ s3_state_config_file = @config["s3_dir"] + "/state.yaml"
+
+ system("/opt/awscli/v2/current/bin/aws", "--profile=osm-pds-upload", "s3", "cp", "--storage-class=INTELLIGENT_TIERING", "--no-progress", data_file, s3_file)
+ system("/opt/awscli/v2/current/bin/aws", "--profile=osm-pds-upload", "s3", "cp", "--storage-class=INTELLIGENT_TIERING", "--no-progress", data_state_file, s3_state_file)
+ system("/opt/awscli/v2/current/bin/aws", "--profile=osm-pds-upload", "s3", "cp", "--storage-class=INTELLIGENT_TIERING", "--no-progress", @config["state_file"], s3_state_config_file)
+ end
end
# saves new state (including the changeset dump xml)
# of processes queueing on the lock and causing weirdness if/when they
# get woken up in a random order.
got_lock = fl.flock(File::LOCK_EX | File::LOCK_NB)
- return unless got_lock
+ break unless got_lock
# try and write the files to tmp locations and then
# move them into place later, to avoid in-progress
rep.save!
rescue StandardError => e
warn "ERROR: #{e.message}"
+ e.backtrace.each do |frame|
+ warn "ERROR: #{frame}"
+ end
exit 1
end
--- /dev/null
+#!/bin/sh
+
+set -e
+
+find /var/lib/replication/minute -name *.done -mtime +14 -print0 | xargs -0r rm
--- /dev/null
+#!/bin/sh
+
+set -e
+
+/usr/local/bin/osmosis -q --merge-replication-files workingDirectory=/var/lib/replication/day
+
+. /store/planet/replication/day/state.txt
+
+sequencePart1=$(($sequenceNumber / 1000000 % 1000))
+sequencePart2=$(($sequenceNumber / 1000 % 1000))
+sequencePart3=$(($sequenceNumber % 1000))
+diffPath=$(printf "%03d/%03d/%03d" $sequencePart1 $sequencePart2 $sequencePart3)
+
+/opt/awscli/v2/current/bin/aws --profile=osm-pds-upload s3 cp --storage-class=INTELLIGENT_TIERING --no-progress "/store/planet/replication/day/${diffPath}.osc.gz" "s3://osm-planet-eu-central-1/planet/replication/day/${diffPath}.osc.gz"
+/opt/awscli/v2/current/bin/aws --profile=osm-pds-upload s3 cp --storage-class=INTELLIGENT_TIERING --no-progress "/store/planet/replication/day/${diffPath}.state.txt" "s3://osm-planet-eu-central-1/planet/replication/day/${diffPath}.state.txt"
+/opt/awscli/v2/current/bin/aws --profile=osm-pds-upload s3 cp --storage-class=INTELLIGENT_TIERING --no-progress "/store/planet/replication/day/state.txt" "s3://osm-planet-eu-central-1/planet/replication/day/state.txt"
--- /dev/null
+#!/bin/sh
+
+set -e
+
+/usr/local/bin/osmosis -q --merge-replication-files workingDirectory=/var/lib/replication/hour
+
+. /store/planet/replication/hour/state.txt
+
+sequencePart1=$(($sequenceNumber / 1000000 % 1000))
+sequencePart2=$(($sequenceNumber / 1000 % 1000))
+sequencePart3=$(($sequenceNumber % 1000))
+diffPath=$(printf "%03d/%03d/%03d" $sequencePart1 $sequencePart2 $sequencePart3)
+
+/opt/awscli/v2/current/bin/aws --profile=osm-pds-upload s3 cp --storage-class=INTELLIGENT_TIERING --no-progress "/store/planet/replication/hour/${diffPath}.osc.gz" "s3://osm-planet-eu-central-1/planet/replication/hour/${diffPath}.osc.gz"
+/opt/awscli/v2/current/bin/aws --profile=osm-pds-upload s3 cp --storage-class=INTELLIGENT_TIERING --no-progress "/store/planet/replication/hour/${diffPath}.state.txt" "s3://osm-planet-eu-central-1/planet/replication/hour/${diffPath}.state.txt"
+/opt/awscli/v2/current/bin/aws --profile=osm-pds-upload s3 cp --storage-class=INTELLIGENT_TIERING --no-progress "/store/planet/replication/hour/state.txt" "s3://osm-planet-eu-central-1/planet/replication/hour/state.txt"
--- /dev/null
+#!/bin/sh
+
+set -e
+
+cd /etc/replication
+
+osmdbt-catchup --quiet
+osmdbt-get-log --quiet
+
+/opt/awscli/v2/current/bin/aws --profile=osm-osmdbt-state-upload s3 sync --storage-class=INTELLIGENT_TIERING --no-progress --exclude='*' --include='osm-repl-*.log' /var/lib/replication/minute s3://openstreetmap-osmdbt-state
+
+osmdbt-catchup --quiet
+osmdbt-create-diff --quiet --with-comment --max-changes=50000
+
+. /store/planet/replication/minute/state.txt
+
+sequencePart1=$(($sequenceNumber / 1000000 % 1000))
+sequencePart2=$(($sequenceNumber / 1000 % 1000))
+sequencePart3=$(($sequenceNumber % 1000))
+diffPath=$(printf "%03d/%03d/%03d" $sequencePart1 $sequencePart2 $sequencePart3)
+
+/opt/awscli/v2/current/bin/aws --profile=osm-pds-upload s3 cp --storage-class=INTELLIGENT_TIERING --no-progress "/store/planet/replication/minute/${diffPath}.osc.gz" "s3://osm-planet-eu-central-1/planet/replication/minute/${diffPath}.osc.gz"
+/opt/awscli/v2/current/bin/aws --profile=osm-pds-upload s3 cp --storage-class=INTELLIGENT_TIERING --no-progress "/store/planet/replication/minute/${diffPath}.state.txt" "s3://osm-planet-eu-central-1/planet/replication/minute/${diffPath}.state.txt"
+/opt/awscli/v2/current/bin/aws --profile=osm-pds-upload s3 cp --storage-class=INTELLIGENT_TIERING --no-progress "/store/planet/replication/minute/state.txt" "s3://osm-planet-eu-central-1/planet/replication/minute/state.txt"
+++ /dev/null
-#!/bin/sh
-
-# DO NOT EDIT - This file is being maintained by Chef
-
-export TZ=UTC
-
-exec >> /var/log/replication/streaming-replicator 2>&1
-
-exec /usr/local/bin/osmosis -q \
- --replicate-apidb iterations=0 minInterval=10000 maxInterval=60000 authFile=/etc/replication/auth.conf validateSchemaVersion=false \
- --send-replication-sequence port=8081 \
- --write-replication workingDirectory=/var/lib/replication/streaming
+++ /dev/null
-#!/bin/sh
-
-# DO NOT EDIT - This file is being maintained by Chef
-
-export TZ=UTC
-
-exec >> /var/log/replication/streaming-server 2>&1
-
-exec /usr/local/bin/osmosis -q \
- --send-replication-data dataDirectory=/var/lib/replication/streaming port=8080 notificationPort=8081
-#!/usr/bin/env python
+#!/usr/bin/python3
-print """
+print("""
<html>
<head>
<title>OpenStreetMap replication diffs</title>
<h1>planet.openstreetmap.org - replication diffs</h1>
<p>OpenStreetMap is <i>open data</i>, licensed under the <a href="https://opendatacommons.org/licenses/odbl/">Open Data Commons Open Database License</a> (ODbL)</p>
<p> </p>
-"""
+""")
depends "accounts"
depends "apache"
depends "apt"
+depends "awscli"
+depends "geoipupdate"
depends "git"
-depends "incron"
-depends "munin"
+depends "ruby"
depends "osmosis"
depends "systemd"
--- /dev/null
+#
+# Cookbook:: planet
+# Recipe:: aws
+#
+# Copyright:: 2023, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "accounts"
+include_recipe "awscli"
+
+aws_credentials = data_bag_item("planet", "aws")
+
+directory "/home/planet/.aws" do
+ owner "planet"
+ group "planet"
+ mode "0755"
+end
+
+template "/home/planet/.aws/config" do
+ source "aws-config.erb"
+ owner "planet"
+ group "planet"
+ mode "0644"
+end
+
+template "/home/planet/.aws/credentials" do
+ source "aws-credentials.erb"
+ owner "planet"
+ group "planet"
+ mode "0600"
+ variables :credentials => aws_credentials
+end
# limitations under the License.
#
+node.default[:accounts][:users][:planet][:status] = :role
+
include_recipe "accounts"
package %w[
mode "755"
end
-template "/usr/local/bin/planet-update-file" do
- source "planet-update-file.erb"
- owner "root"
- group "root"
- mode "755"
-end
-
directory "/var/lib/planet" do
owner "planet"
group "planet"
owner "planet"
group "planet"
mode "644"
- not_if { ENV["TEST_KITCHEN"] }
+ not_if { kitchen? }
end
-cron_d "planet-update" do
- minute "17"
- hour "1"
- user "root"
- command "/usr/local/bin/planet-update"
-end
-
-template "/etc/logrotate.d/planet-update" do
- source "planet-update.logrotate.erb"
- owner "root"
- group "root"
- mode "644"
+systemd_service "planet-update" do
+ description "Planet file update"
+ type "oneshot"
+ exec_start "/usr/local/bin/planet-update"
+ user "planet"
+ sandbox :enable_network => true
+ read_write_paths "/var/lib/planet"
end
include_recipe "accounts"
include_recipe "apache"
-include_recipe "munin"
+include_recipe "geoipupdate"
+include_recipe "planet::aws"
package %w[
- perl
- php-cli
+ python3
+ python3-geoip2
]
remote_directory "/store/planet#html" do
remote_directory node[:planet][:dump][:xml_history_directory] do
source "history_cgi"
- owner "www-data"
+ owner "planet"
+ group "planet"
+ mode "775"
+ files_owner "root"
+ files_group "root"
+ files_mode "755"
+end
+
+remote_directory "/store/planet/cc-by-sa" do
+ source "ccbysa_cgi"
+ owner "planet"
group "planet"
mode "775"
files_owner "root"
remote_directory "/store/planet/cc-by-sa/full-experimental" do
source "ccbysa_history_cgi"
- owner "www-data"
+ owner "planet"
group "planet"
mode "775"
files_owner "root"
[:xml_directory, :xml_history_directory,
:pbf_directory, :pbf_history_directory].each do |dir|
directory node[:planet][:dump][dir] do
- owner "www-data"
+ owner "planet"
group "planet"
mode "775"
end
end
directory "/store/planet/notes" do
- owner "www-data"
+ owner "planet"
+ group "planet"
+ mode "775"
+end
+
+directory "/store/planet/statistics" do
+ owner "planet"
group "planet"
mode "775"
end
notifies :restart, "service[apache2]"
end
+template "/usr/local/bin/apache-s3-ip2region" do
+ source "apache-s3-ip2region.erb"
+ owner "root"
+ group "root"
+ mode "755"
+ notifies :restart, "service[apache2]"
+end
+
apache_module "cgid"
apache_module "rewrite"
apache_module "proxy_http"
mode "644"
end
-munin_plugin "planet_age"
-
-template "/usr/local/bin/old-planet-file-cleanup" do
- source "old-planet-file-cleanup.erb"
+template "/usr/local/bin/planet-file-cleanup" do
+ source "planet-file-cleanup.erb"
owner "root"
group "root"
mode "755"
end
-cron_d "old-planet-file-cleanup" do
- comment "run this on the first monday of the month at 3:44am"
- minute "44"
- hour "3"
- day "1-7"
- user "www-data"
- command "test $(date +\\%u) -eq 1 && /usr/local/bin/old-planet-file-cleanup --debug"
- mailto "zerebubuth@gmail.com"
+systemd_service "planet-file-cleanup" do
+ description "Cleanup old planet files"
+ exec_start "/usr/local/bin/planet-file-cleanup --debug"
+ user "planet"
+ sandbox true
+ read_write_paths [
+ node[:planet][:dump][:xml_directory],
+ node[:planet][:dump][:pbf_directory]
+ ]
+end
+
+systemd_timer "planet-file-cleanup" do
+ description "Cleanup old planet files"
+ on_calendar "Mon *-*-1..7 03:44"
+end
+
+service "planet-file-cleanup.timer" do
+ action [:enable, :start]
end
# limitations under the License.
#
-node.default[:incron][:planetdump] = {
- :user => "root",
- :path => "/store/backup",
- :events => %w[IN_CREATE IN_MOVED_TO],
- :command => "/bin/systemctl start planetdump@$#"
-}
-
+include_recipe "accounts"
include_recipe "git"
-include_recipe "incron"
package %w[
gcc
libprotobuf-dev
osmpbf-bin
pbzip2
- php-cli
- php-curl
mktorrent
xmlstarlet
libxml2-utils
+ inotify-tools
]
directory "/opt/planet-dump-ng" do
git "/opt/planet-dump-ng" do
action :sync
repository "https://github.com/zerebubuth/planet-dump-ng.git"
- revision "v1.2.0"
+ revision "v1.2.7"
depth 1
user "root"
group "root"
end
directory "/store/planetdump" do
- owner "www-data"
- group "www-data"
+ owner "planet"
+ group "planet"
mode "755"
recursive true
end
-%w[planetdump planet-mirror-redirect-update].each do |program|
+%w[planetdump planetdump-trigger].each do |program|
template "/usr/local/bin/#{program}" do
source "#{program}.erb"
owner "root"
systemd_service "planetdump@" do
description "Planet dump for %i"
- user "www-data"
+ user "planet"
exec_start "/usr/local/bin/planetdump %i"
memory_max "64G"
- private_tmp true
- private_devices true
- private_network true
- protect_system "full"
- protect_home true
- no_new_privileges true
+ sandbox :enable_network => true
+ protect_home "tmpfs"
+ bind_paths "/home/planet"
+ read_write_paths [
+ "/store/planetdump",
+ "/store/planet/pbf",
+ "/store/planet/planet",
+ "/var/log/exim4",
+ "/var/spool/exim4"
+ ]
+end
+
+systemd_service "planetdump-trigger" do
+ description "Planet dump trigger"
+ user "root"
+ exec_start "/usr/local/bin/planetdump-trigger"
+ sandbox true
+ restrict_address_families "AF_UNIX"
end
-cron_d "planet-dump-mirror" do
- minute "*/10"
- user "www-data"
- command "/usr/local/bin/planet-mirror-redirect-update"
- mailto "horntail-www-data-cron@firefishy.com"
+service "planetdump-trigger" do
+ action [:enable, :start]
+ subscribes :restart, "template[/usr/local/bin/planetdump-trigger]"
end
# limitations under the License.
#
+include_recipe "accounts"
include_recipe "git"
+include_recipe "planet::aws"
db_passwords = data_bag_item("db", "passwords")
variables :password => db_passwords["planetdump"]
end
-cron_d "planet-notes-dump" do
- minute "0"
- hour "3"
- user "www-data"
- command "/usr/local/bin/planet-notes-dump"
- mailto "grant-smaug@firefishy.com"
+systemd_service "planet-notes-dump" do
+ description "Create notes dump"
+ exec_start "/usr/local/bin/planet-notes-dump"
+ user "planet"
+ sandbox :enable_network => true
+ protect_home "tmpfs"
+ bind_paths "/home/planet"
+ read_write_paths "/store/planet/notes"
end
-cron_d "planet-notes-cleanup" do
- comment "Delete Planet Notes dump files older than 8 days"
- minute "10"
- hour "8"
- user "www-data"
- command "find /store/planet/notes/20??/ -maxdepth 1 -type f -iname 'planet-notes-??????.osn*' -printf '\%T@ \%p\n' | sort -k 1nr | sed 's/^[^ ]* //' | tail -n +17 | xargs -r rm -f"
- mailto "grant-smaug@firefishy.com"
+systemd_timer "planet-notes-dump" do
+ description "Create notes dump"
+ on_calendar "03:00"
+end
+
+service "planet-notes-dump.timer" do
+ action [:enable, :start]
+end
+
+template "/usr/local/bin/planet-notes-cleanup" do
+ source "planet-notes-cleanup.erb"
+ owner "root"
+ group "root"
+ mode "755"
+end
+
+systemd_service "planet-notes-cleanup" do
+ description "Delete old notes dumps"
+ exec_start "/usr/local/bin/planet-notes-cleanup"
+ user "planet"
+ sandbox true
+ read_write_paths "/store/planet/notes"
+end
+
+systemd_timer "planet-notes-cleanup" do
+ description "Delete old notes dumps"
+ on_calendar "08:10"
+end
+
+service "planet-notes-cleanup.timer" do
+ action [:enable, :start]
end
include_recipe "accounts"
include_recipe "apt"
include_recipe "osmosis"
+include_recipe "planet::aws"
+include_recipe "ruby"
+include_recipe "tools"
db_passwords = data_bag_item("db", "passwords")
package %w[
postgresql-client
- ruby
- ruby-dev
ruby-libxml
make
gcc
osmdbt
]
-gem_package "pg"
+gem_package "pg" do
+ gem_binary node[:ruby][:gem]
+end
## Build preload library to flush files
files_mode "755"
end
-template "/usr/local/bin/replicate-minute" do
- source "replicate-minute.erb"
- owner "root"
- group "root"
- mode "755"
-end
-
template "/usr/local/bin/users-agreed" do
source "users-agreed.erb"
owner "root"
variables :password => db_passwords["planetdiff"]
end
+systemd_service "users-agreed" do
+ description "Update list of users accepting CTs"
+ user "planet"
+ exec_start "/usr/local/bin/users-agreed"
+ nice 10
+ sandbox :enable_network => true
+ read_write_paths "/store/planet/users_agreed"
+end
+
+systemd_timer "users-agreed" do
+ description "Update list of users accepting CTs"
+ on_calendar "7:00"
+end
+
+systemd_service "users-deleted" do
+ description "Update list of deleted users"
+ user "planet"
+ exec_start "/usr/local/bin/users-deleted"
+ nice 10
+ sandbox :enable_network => true
+ read_write_paths "/store/planet/users_deleted"
+end
+
+systemd_timer "users-deleted" do
+ description "Update list of deleted users"
+ on_calendar "17:00"
+end
+
## Changeset replication
directory "/store/planet/replication/changesets" do
variables :password => db_passwords["planetdiff"]
end
+systemd_service "replication-changesets" do
+ description "Changesets replication"
+ user "planet"
+ exec_start "/usr/local/bin/replicate-changesets /etc/replication/changesets.conf"
+ sandbox :enable_network => true
+ protect_home "tmpfs"
+ bind_paths "/home/planet"
+ read_write_paths [
+ "/run/replication",
+ "/store/planet/replication/changesets"
+ ]
+end
+
+systemd_timer "replication-changesets" do
+ description "Changesets replication"
+ on_boot_sec 60
+ on_unit_active_sec 60
+ accuracy_sec 5
+end
+
## Minutely replication
directory "/store/planet/replication/minute" do
user "planet"
working_directory "/etc/replication"
exec_start "/usr/local/bin/replicate-minute"
- private_tmp true
- private_devices true
- protect_system "full"
- protect_home true
- restrict_address_families %w[AF_INET AF_INET6]
- no_new_privileges true
+ sandbox :enable_network => true
+ protect_home "tmpfs"
+ bind_paths "/home/planet"
+ read_write_paths [
+ "/run/replication",
+ "/store",
+ "/var/lib/replication/minute"
+ ]
end
systemd_timer "replication-minutely" do
systemd_service "replication-hourly" do
description "Hourly replication"
user "planet"
- exec_start "/usr/local/bin/osmosis -q --merge-replication-files workingDirectory=/var/lib/replication/hour"
- private_tmp true
- private_devices true
- protect_system "full"
- protect_home true
- restrict_address_families %w[AF_INET AF_INET6]
- no_new_privileges true
+ exec_start "/usr/local/bin/replicate-hour"
+ environment "LD_PRELOAD" => "/opt/flush/flush.so"
+ sandbox :enable_network => true
+ memory_deny_write_execute false
+ protect_home "tmpfs"
+ bind_paths "/home/planet"
+ read_write_paths [
+ "/store/planet/replication/hour",
+ "/var/lib/replication/hour"
+ ]
end
systemd_timer "replication-hourly" do
- description "Daily replication"
+ description "Hourly replication"
on_calendar "*-*-* *:02/15:00"
end
systemd_service "replication-daily" do
description "Daily replication"
user "planet"
- exec_start "/usr/local/bin/osmosis -q --merge-replication-files workingDirectory=/var/lib/replication/day"
- private_tmp true
- private_devices true
- protect_system "full"
- protect_home true
- restrict_address_families %w[AF_INET AF_INET6]
- no_new_privileges true
+ exec_start "/usr/local/bin/replicate-day"
+ environment "LD_PRELOAD" => "/opt/flush/flush.so"
+ sandbox :enable_network => true
+ memory_deny_write_execute false
+ protect_home "tmpfs"
+ bind_paths "/home/planet"
+ read_write_paths [
+ "/store/planet/replication/day",
+ "/var/lib/replication/day"
+ ]
end
systemd_timer "replication-daily" do
on_calendar "*-*-* *:02/15:00"
end
+## Replication cleanup
+
+systemd_service "replication-cleanup" do
+ description "Cleanup replication"
+ user "planet"
+ exec_start "/usr/local/bin/replicate-cleanup"
+ sandbox true
+ read_write_paths "/var/lib/replication"
+end
+
+systemd_timer "replication-cleanup" do
+ description "Cleanup replication"
+ on_boot_sec 60
+ on_unit_active_sec 86400
+ accuracy_sec 1800
+end
+
## Enable/disable feeds
if node[:planet][:replication] == "enabled"
- cron_d "users-agreed" do
- minute "0"
- hour "7"
- user "planet"
- command "/usr/local/bin/users-agreed"
- mailto "zerebubuth@gmail.com"
+ service "users-agreed.timer" do
+ action [:enable, :start]
end
- cron_d "users-deleted" do
- minute "0"
- hour "17"
- user "planet"
- command "/usr/local/bin/users-deleted"
- mailto "zerebubuth@gmail.com"
+ service "users-deleted.timer" do
+ action [:enable, :start]
end
- cron_d "replication-changesets" do
- user "planet"
- command "/usr/local/bin/replicate-changesets /etc/replication/changesets.conf"
- mailto "zerebubuth@gmail.com"
+ service "replication-changesets.timer" do
+ action [:enable, :start]
end
service "replication-minutely.timer" do
service "replication-daily.timer" do
action [:enable, :start]
end
+
+ service "replication-cleanup.timer" do
+ action [:enable, :start]
+ end
else
- cron_d "users-agreed" do
- action :delete
+ service "users-agreed.timer" do
+ action [:stop, :disable]
end
- cron_d "users-deleted" do
- action :delete
+ service "users-deleted.timer" do
+ action [:stop, :disable]
end
- cron_d "replication-changesets" do
- action :delete
+ service "replication-changesets.timer" do
+ action [:stop, :disable]
end
service "replication-minutely.timer" do
service "replication-daily.timer" do
action [:stop, :disable]
end
+
+ service "replication-cleanup.timer" do
+ action [:stop, :disable]
+ end
end
-#!/usr/bin/perl
+#!/usr/bin/python3
# DO NOT EDIT - This file is being maintained by Chef
-use strict;
-use warnings;
+import os
+import sys
-use Cwd qw(abs_path);
+def main():
+ for line in sys.stdin:
+ path = line.strip()
-$| = 1;
+ # Construct the file path and resolve its real path,
+ # which will consider any symbolic links
+ file = os.path.realpath(f"/store/planet{path}")
-while (my $path = <STDIN>)
-{
- chomp $path;
+ # Check if the constructed file path starts with '/store/planet'
+ # and if the file actually exists
+ if file.startswith('/store/planet') and os.path.isfile(file):
+ # Print the portion of the path after '/store/planet'
+ # and immediately flush the output
+ print(file[len('/store/planet'):], flush=True)
+ else:
+ # If the file does not exist or the path does not start with
+ # the expected prefix, print "NULL" and flush the output
+ print("NULL", flush=True)
- my $file = abs_path("/store/planet${path}");
-
- if ($file && $file =~ m|^/store/planet(/.*)$| && -f $file)
- {
- print "$1\n";
- }
- else
- {
- print "NULL\n";
- }
-}
+if __name__ == "__main__":
+ main()
--- /dev/null
+#!/usr/bin/env python3
+
+import sys
+import os
+import geoip2.database
+import ipaddress
+
+# Constants
+DB_PATH = "<%= node[:geoipupdate][:directory] %>/GeoLite2-Country.mmdb"
+
+# Default region when continent doesn't match any in the dictionary
+DEFAULT_REGION = "eu-central-1"
+
+# Mapping of continents to AWS regions
+CONTINENT_TO_AWS_REGION = {
+ "NA": "us-west-2", # North America
+ "OC": "us-west-2", # Oceania
+ "SA": "us-west-2", # South America
+}
+
+# Global to store last known modification time and database reader
+last_mod_time = None
+reader = None
+
+def is_valid_ip(ip_str):
+ """Check if a string is a valid IPv4 or IPv6 address."""
+ try:
+ ipaddress.ip_address(ip_str)
+ return True
+ except ValueError:
+ return False
+
+def get_reader():
+ """Get the geoip2 database reader. Reload if the DB file has changed."""
+ global last_mod_time
+ global reader
+
+ if not os.path.exists(DB_PATH):
+ return None # Database file missing
+
+ current_mod_time = os.path.getmtime(DB_PATH)
+
+ # If file has changed or reader isn't initialized, reload it
+ if reader is None or current_mod_time != last_mod_time:
+ if reader:
+ reader.close() # Close the existing reader before reinitializing
+ reader = geoip2.database.Reader(DB_PATH)
+ last_mod_time = current_mod_time
+
+ return reader
+
+def get_continent_from_ip(ip_address):
+ """Return the continent for a given IP address."""
+ if not is_valid_ip(ip_address):
+ return None
+ reader = get_reader()
+ if reader is None:
+ return None # No continent as DB is missing
+ try:
+ response = reader.country(ip_address)
+ return response.continent.code
+ except:
+ return None # Indicates invalid IP address or other issues
+
+def determine_aws_region(continent_code):
+ """Determine AWS region based on the continent code using a dictionary."""
+ return CONTINENT_TO_AWS_REGION.get(continent_code, DEFAULT_REGION)
+
+def main():
+ """Main function to process IP addresses from stdin and return AWS regions."""
+ for line in sys.stdin:
+ ip_address = line.strip()
+
+ continent_code = get_continent_from_ip(ip_address)
+ aws_region = determine_aws_region(continent_code)
+
+ sys.stdout.write(f"{aws_region}\n")
+ sys.stdout.flush()
+
+if __name__ == "__main__":
+ main()
ServerAlias planet.osm.org
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/planet.openstreetmap.org-access.log combined
+ CustomLog /var/log/apache2/planet.openstreetmap.org-access.log combined_extended
ErrorLog /var/log/apache2/planet.openstreetmap.org-error.log
SSLEngine on
Require all granted
</Directory>
- ProxyPass /replication/streaming http://127.0.0.1:8080
-
- <Location /replication/steaming>
- Require all granted
- </Location>
-
Redirect /pbf-experimental/ /pbf/
<IfModule mod_headers.c>
- Header set Access-Control-Allow-Origin "*"
+ Header always set Access-Control-Allow-Origin "*"
</IfModule>
RewriteEngine on
RewriteMap latestplanet prg:/usr/local/bin/apache-latest-planet-filename
+ RewriteMap ip2region prg:/usr/local/bin/apache-s3-ip2region
- #Direct, no redirect for the following
- RewriteCond %{REMOTE_ADDR} ^127\. [OR]
- RewriteCond %{REMOTE_ADDR} ^10\. [OR]
- RewriteCond %{REMOTE_ADDR} ^193\.60\. [OR]
- RewriteCond %{REMOTE_ADDR} ^193\.61\. [OR]
- RewriteCond %{REMOTE_ADDR} ^193\.62\. [OR]
- RewriteCond %{REMOTE_ADDR} ^193\.63\. [OR]
+ # Direct, no redirect for the following
+ RewriteCond %{REMOTE_ADDR} ^(127\.|10\.|192\.168\.)
RewriteCond %{QUERY_STRING} nomirror
- RewriteRule .* - [L]
+ RewriteRule .* - [L]
+ # Use RewriteMap latestplanet to redirect -latest symlink to resolved file eg: planet-latest.osm.bz2 -> 2023/planet-230918.osm.bz2
RewriteRule ^(/planet/planet\-latest\.osm\.bz2(\.torrent)?)$ ${latestplanet:$1} [R,L]
RewriteRule ^(/planet/full\-history/history\-latest\.osm\.bz2(\.torrent)?)$ ${latestplanet:$1} [R,L]
RewriteRule ^(/planet/changesets\-latest\.osm\.bz2(\.torrent)?)$ ${latestplanet:$1} [R,L]
RewriteRule ^(/cc\-by\-sa/changesets\-latest\.osm\.bz2)$ ${latestplanet:$1} [R,L]
RewriteRule ^(/cc\-by\-sa/relations\-latest\.osm\.bz2)$ ${latestplanet:$1} [R,L]
- # Block an abusive fake user agent
- RewriteCond %{HTTP_USER_AGENT} "=Mozilla/5.0 (Linux; Android) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36"
- RewriteRule /.*$ - [F,L]
-
- # Temporary download rate limit due to upstream fibre connection issues. - 13 Jan 2020
- <FilesMatch ".+\.(7z|bz2|gz|pbf|tgz|xz)$">
- SetOutputFilter RATE_LIMIT
- SetEnv rate-limit 4096
- SetEnv rate-initial-burst 8192
- </FilesMatch>
+ RewriteRule ^(/notes/planet\-notes\-latest\.osn\.bz2)$ ${latestplanet:$1} [R,L]
+
+ # Redirect minute/hour/day replication files to AWS S3 eu-central-1 bucket
+ RewriteRule ^/replication/((minute|hour|day)/state\.txt)$ https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/planet/replication/$1 [R,L]
+ RewriteRule ^/replication/((minute|hour|day)/\d{3}/\d{3}/\d{3}\.state\.txt)$ https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/planet/replication/$1 [R,L]
+ RewriteRule ^/replication/((minute|hour|day)/\d{3}/\d{3}/\d{3}\.osc\.gz)$ https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/planet/replication/$1 [R,L]
+
+ # Redirect changeset replication files to AWS S3 eu-central-1 bucket
+ RewriteRule ^/replication/changesets/(state\.yaml)$ https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/changesets/replication/minute/$1 [R,L]
+ RewriteRule ^/replication/changesets/(\d{3}/\d{3}/\d{3}\.state\.txt)$ https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/changesets/replication/minute/$1 [R,L]
+ RewriteRule ^/replication/changesets/(\d{3}/\d{3}/\d{3}\.osm\.gz)$ https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/changesets/replication/minute/$1 [R,L]
+
+ # Set ENV:REGION to AWS region closest to the user
+ RewriteRule .* - [E=REGION:${ip2region:%{REMOTE_ADDR}|eu-central-1}]
+
+ <% start_year = 2008 %>
+ <% current_year = Time.now.year %>
+ <% (start_year..current_year).each do |year| %>
+ <% year_two = sprintf('%02d', year % 100) %>
+ RewriteRule ^/pbf/(planet\-<%= year_two %>[0-1][0-9][0-3][0-9]\.osm\.pbf(\.torrent|\.md5)?)$ https://osm-planet-%{ENV:REGION}.s3.dualstack.%{ENV:REGION}.amazonaws.com/planet/pbf/<%= year %>/$1 [R,L]
+ RewriteRule ^/pbf/full\-history/(history\-<%= year_two %>[0-1][0-9][0-3][0-9]\.osm\.pbf(\.torrent|\.md5)?)$ https://osm-planet-%{ENV:REGION}.s3.dualstack.%{ENV:REGION}.amazonaws.com/planet-full-history/pbf/<%= year %>/$1 [R,L]
+ RewriteRule ^/planet/<%= year %>/(planet\-<%= year_two %>[0-1][0-9][0-3][0-9]\.osm\.bz2(\.torrent|\.md5)?)$ https://osm-planet-%{ENV:REGION}.s3.dualstack.%{ENV:REGION}.amazonaws.com/planet/osm/<%= year %>/$1 [R,L]
+ RewriteRule ^/planet/<%= year %>/(changesets\-<%= year_two %>[0-1][0-9][0-3][0-9]\.osm\.bz2(\.torrent|\.md5)?)$ https://osm-planet-%{ENV:REGION}.s3.dualstack.%{ENV:REGION}.amazonaws.com/changesets/osm/<%= year %>/$1 [R,L]
+ RewriteRule ^/planet/<%= year %>/(discussions\-<%= year_two %>[0-1][0-9][0-3][0-9]\.osm\.bz2(\.torrent|\.md5)?)$ https://osm-planet-%{ENV:REGION}.s3.dualstack.%{ENV:REGION}.amazonaws.com/discussions/osm/<%= year %>/$1 [R,L]
+ RewriteRule ^/planet/full\-history/<%= year %>/(history\-<%= year_two %>[0-1][0-9][0-3][0-9]\.osm\.bz2(\.torrent|\.md5)?)$ https://osm-planet-%{ENV:REGION}.s3.dualstack.%{ENV:REGION}.amazonaws.com/planet-full-history/osm/<%= year %>/$1 [R,L]
+ RewriteRule ^/notes/<%= year %>/(planet\-notes\-<%= year_two %>[0-1][0-9][0-3][0-9]\.osn\.bz2(\.md5)?)$ https://osm-planet-%{ENV:REGION}.s3.dualstack.%{ENV:REGION}.amazonaws.com/notes/osn/<%= year %>/$1 [R,L]
+ RewriteRule ^/tile_logs/(hosts\-<%= year %>\-[01][0-9]\-[0-3][0-9]\.csv)$ https://osm-planet-%{ENV:REGION}.s3.dualstack.%{ENV:REGION}.amazonaws.com/tile_logs/standard_layer/hosts/<%= year %>/$1 [R,L]
+ RewriteRule ^/tile_logs/(countries\-<%= year %>\-[01][0-9]\-[0-3][0-9]\.csv)$ https://osm-planet-%{ENV:REGION}.s3.dualstack.%{ENV:REGION}.amazonaws.com/tile_logs/standard_layer/countries/<%= year %>/$1 [R,L]
+ RewriteRule ^/tile_logs/(apps\-<%= year %>\-[01][0-9]\-[0-3][0-9]\.csv)$ https://osm-planet-%{ENV:REGION}.s3.dualstack.%{ENV:REGION}.amazonaws.com/tile_logs/standard_layer/apps/<%= year %>/$1 [R,L]
+ RewriteRule ^/tile_logs/(tiles\-<%= year %>\-[01][0-9]\-[0-3][0-9]\.txt\.xz)$ https://osm-planet-%{ENV:REGION}.s3.dualstack.%{ENV:REGION}.amazonaws.com/tile_logs/standard_layer/tiles/<%= year %>/$1 [R,L]
+ <% end %>
</VirtualHost>
<VirtualHost *:80>
ServerAlias planet.osm.org
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/planet.openstreetmap.org-access.log combined
+ CustomLog /var/log/apache2/planet.openstreetmap.org-access.log combined_extended
ErrorLog /var/log/apache2/planet.openstreetmap.org-error.log
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
--- /dev/null
+[profile osm-pds]
+region = eu-central-1
+
+[profile osm-pds-upload]
+region = eu-central-1
+s3 =
+ max_bandwidth = 150MB/s
+ max_concurrent_requests = 256
+
+[profile osm-osmdbt-state]
+region = eu-west-1
+
+[profile osm-osmdbt-state-upload]
+region = eu-west-1
+s3 =
+ max_bandwidth = 100MB/s
+ max_concurrent_requests = 256
--- /dev/null
+[osm-pds]
+aws_access_key_id = AKIAZFVRMSDZE2DANIFS
+aws_secret_access_key = <%= @credentials["osm-pds"] %>
+
+[osm-pds-upload]
+role_arn=arn:aws:iam::630658470130:role/osm-pds-upload-role
+source_profile=osm-pds
+
+[osm-osmdbt-state]
+aws_access_key_id = AKIASQUXHPE7BNEKJFRQ
+aws_secret_access_key = <%= @credentials["osm-osmdbt-state"] %>
+
+[osm-osmdbt-state-upload]
+role_arn=arn:aws:iam::173189593406:role/osm-osmdbt-state-upload-role
+source_profile=osm-osmdbt-state
state_file: /store/planet/replication/changesets/state.yaml
db: host=<%= node[:web][:database_host] %> dbname=openstreetmap user=planetdiff password=<%= @password %>
data_dir: /store/planet/replication/changesets
+s3_dir: s3://osm-planet-eu-central-1/changesets/replication/minute
lock_file: /run/replication/changesets.lock
+++ /dev/null
-#!/usr/bin/php
-<?php
-/*
- DO NOT EDIT - This file is being maintained by Chef
-
- planet-mirror-redirect
- Check if planet file exists on mirror and link if not yet linked
- Modifies .htaccess
-*/
-$_YEAR = date('Y');
-
-$_MIRROR = 'https://ftp5.gwdg.de/pub/misc/openstreetmap/planet.openstreetmap.org/';
-
-$_FOLDERS = [
- "planet_bz2" => [
- 'FOLDER' => '<%= node[:planet][:dump][:xml_directory] %>/'.$_YEAR.'/',
- 'REGEX' => '/^(planet|changesets|discussions)\-\d{6}(\-nolt)?\.osm\.(bz2|gz)$/',
- 'DIR_PREFIX' => 'planet/'.$_YEAR.'/'
- ],
-
- "history_bz2" => [
- 'FOLDER' => '<%= node[:planet][:dump][:xml_history_directory] %>/'.$_YEAR.'/',
- 'REGEX' => '/^(history)\-\d{6}(\-nolt)?\.osm\.(bz2|gz)$/',
- 'DIR_PREFIX' => 'planet/full-history/'.$_YEAR.'/'
- ],
- "planet_pbf" => [
- 'FOLDER' => '<%= node[:planet][:dump][:pbf_directory] %>/',
- 'REGEX' => '/^(planet)\-\d{6}(\-nolt)?\.osm\.pbf$/',
- 'DIR_PREFIX' => 'pbf/'
- ],
-
- "history_pbf" => [
- 'FOLDER' => '<%= node[:planet][:dump][:pbf_history_directory] %>/',
- 'REGEX' => '/^(history)\-\d{6}(\-nolt)?\.osm\.pbf$/',
- 'DIR_PREFIX' => 'pbf/full-history/'
- ]
- ];
-
-$_PLANET_HTACCESS = realpath('<%= node[:planet][:dump][:xml_directory] %>/..').'/.htaccess';
-
-function _MIRROR_FILE_SIZE($url) {
- $ch = @curl_init();
- curl_setopt($ch, CURLOPT_URL, $url);
- curl_setopt($ch, CURLOPT_NOBODY, TRUE);
- curl_setopt($ch, CURLOPT_VERBOSE, FALSE);
- $curl_response = @curl_exec($ch);
- $curl_result = curl_getinfo($ch);
- if ($curl_result['http_code']!='200') return FALSE;
- return ($curl_result['download_content_length']);
-}
-
-if (!is_writable($_PLANET_HTACCESS)) die('File '.$_PLANET_HTACCESS.' is not writable by current user.'."\n");
-
-$htaccess_contents = file_get_contents($_PLANET_HTACCESS);
-$htaccess_handle = fopen($_PLANET_HTACCESS, 'a');
-
-foreach ($_FOLDERS as $FOLDER) {
-
- $_PLANET_FOLDER = $FOLDER["FOLDER"];
- $_PLANET_REGEX = $FOLDER["REGEX"];
-
- if (!(is_dir($_PLANET_FOLDER))) {
- continue;
- }
-
- if ($dh = opendir($_PLANET_FOLDER)) {
- while (($file = readdir($dh)) !== false ) {
- if (preg_match($_PLANET_REGEX, $file)) {
- $file_slashed = str_replace(array('.','-'), array('\.','\-'), $FOLDER['DIR_PREFIX'].$file);
- if (strpos($htaccess_contents, $file_slashed) === false) {
- $file_size = filesize($_PLANET_FOLDER.$file);
- sleep(rand(2,5));
- $file_mirror_size = _MIRROR_FILE_SIZE($_MIRROR.$FOLDER['DIR_PREFIX'].$file);
- if ($file_size==$file_mirror_size) {
- echo 'Adding: '.$file."\n";
- fwrite($htaccess_handle, 'RewriteRule'."\t". '^('.$file_slashed.')$'."\t".$_MIRROR.'$1'."\t".'[R,L]'."\n");
- }
- }
- }
- }
- closedir($dh);
- }
-}
-
-fclose($htaccess_handle);
-
--- /dev/null
+#!/bin/bash
+
+exec find /store/planet/notes/20?? -maxdepth 1 -type f -iname 'planet-notes-??????.osn*' -printf '%T@ %p\n' | \
+ sort -k 1nr | \
+ sed 's/^[^ ]* //' | \
+ tail -n +17 | \
+ xargs -r rm -f
sed -e "s/${cur_planet_notes}.bz2/planet-notes-latest.osn.bz2/" "${cur_year}/${cur_planet_notes}.bz2.md5" > planet-notes-latest.osn.bz2.md5
+/opt/awscli/v2/current/bin/aws --profile osm-pds-upload s3 cp --storage-class INTELLIGENT_TIERING --no-progress "${cur_year}/${cur_planet_notes}.bz2.md5" "s3://osm-planet-eu-central-1/notes/osn/${cur_year}/${cur_planet_notes}.bz2.md5"
+/opt/awscli/v2/current/bin/aws --profile osm-pds-upload s3 cp --storage-class INTELLIGENT_TIERING --no-progress "${cur_year}/${cur_planet_notes}.bz2" "s3://osm-planet-eu-central-1/notes/osn/${cur_year}/${cur_planet_notes}.bz2"
+
rm /tmp/planet-notes-dump.lock
+++ /dev/null
-#!/bin/sh
-
-# DO NOT EDIT - This file is being maintained by Chef
-
-# setup
-
-SUFFIX="osh.pbf"
-
-PLANETDIR="/var/lib/planet"
-PLANETPREV="${PLANETDIR}/planet-previous.${SUFFIX}"
-PLANETCURR="${PLANETDIR}/planet.${SUFFIX}"
-PLANETNEW="${PLANETDIR}/planet-new.${SUFFIX}"
-PLANETTMP="${PLANETDIR}/planet-tmp.${SUFFIX}"
-
-pyosmium-up-to-date -v -o "$PLANETNEW" "$PLANETCURR"
-retval=$?
-
-while [ $retval -eq 1 ]; do
- mv "$PLANETNEW" "$PLANETTMP"
- pyosmium-up-to-date -v -o "$PLANETNEW" "$PLANETTMP"
- retval=$?
- rm "$PLANETTMP"
-done
-
-if [ $retval -ne 0 ]; then
- exit $retval
-fi
-
-# cleanup
-
-mv "$PLANETCURR" "$PLANETPREV"
-mv "$PLANETNEW" "$PLANETCURR"
# DO NOT EDIT - This file is being maintained by Chef
-exec > /var/log/planet-update.log 2>&1
+# setup
-echo "Updating planet file..."
+SUFFIX="osh.pbf"
-/sbin/runuser -u planet -- /usr/local/bin/planet-update-file
+PLANETDIR="/var/lib/planet"
+PLANETPREV="${PLANETDIR}/planet-previous.${SUFFIX}"
+PLANETCURR="${PLANETDIR}/planet.${SUFFIX}"
+PLANETNEW="${PLANETDIR}/planet-new.${SUFFIX}"
-echo "Running jobs..."
-<% node[:planet][:current][:jobs].each_value do |job| -%>
+pyosmium-up-to-date -vvv -o "$PLANETNEW" "$PLANETCURR"
+retval=$?
-echo "Running '<%= job[:command] %>' as user '<%= job[:user] %>'..."
+while [ $retval -eq 1 ]; do
+ mv "$PLANETCURR" "$PLANETPREV"
+ mv "$PLANETNEW" "$PLANETCURR"
+ pyosmium-up-to-date -vvv -o "$PLANETNEW" "$PLANETCURR"
+ retval=$?
+done
-/sbin/runuser -u "<%= job[:user] %>" -- "<%= job[:command] %>"
-<% end -%>
+if [ $retval -ne 0 ]; then
+ exit $retval
+fi
-echo "Done."
+# cleanup
+
+mv "$PLANETCURR" "$PLANETPREV"
+mv "$PLANETNEW" "$PLANETCURR"
+++ /dev/null
-/var/log/planet-update.log {
- compress
- notifempty
- missingok
-}
--- /dev/null
+#!/bin/sh
+
+inotifywait --quiet --monitor --event CREATE --event MOVED_TO --include "/osm-[0-9]{4}-[0-9]{2}-[0-9]{2}\\.dmp\$" --format %f /store/backup | \
+ xargs -I %file% systemctl start planetdump@%file%.service
fi
fi
-# Redirect this shell's output to a file. This is so that it
-# can be emailed later, since this script is run from incron
-# and incron doesn't yet support MAILTO like cron does. The
-# command below appears to work in bash as well as dash.
-logfile="/tmp/planetdump.log.$$"
-exec > "${logfile}" 2>&1
-
# Create lock file
echo $$ > /tmp/planetdump.lock
function cleanup {
# Remove the lock file
rm /tmp/planetdump.lock
-
- # Send an email with the output, since incron doesn't yet
- # support doing this in the incrontab
- if [[ -s "$logfile" ]]
- then
- mailx -s "Planet dump output: ${file}" zerebubuth@gmail.com < "${logfile}"
- fi
-
- # Remove the log file
- rm -f "${logfile}"
}
# Remove lock on exit
# Function to create bittorrent files
function mk_torrent {
- type="$1"
- format="$2"
- dir="$3"
- s_year="$4"
- web_dir="${dir}${s_year}"
- name="${type}-${date}.osm.${format}"
- web_path="${web_dir}/${name}"
- rss_web_dir="https://planet.openstreetmap.org/${dir}"
- rss_file="${type}-${format}-rss.xml"
- torrent_file="${name}.torrent"
- torrent_url="${rss_web_dir}${s_year}/${torrent_file}"
+ local type="$1"
+ local format="$2"
+ local dir="$3"
+ local s3path="$4"
+ local s_year="$5"
+ local web_dir="${dir}${s_year}"
+ local name="${type}-${date}.osm.${format}"
+ local web_path="${web_dir}/${name}"
+ local s3_web_path="${s3path}/${name}"
+ local rss_web_dir="https://planet.openstreetmap.org/${dir}"
+ local rss_file="${type}-${format}-rss.xml"
+ local torrent_file="${name}.torrent"
+ local torrent_url="${rss_web_dir}${s_year}/${torrent_file}"
# create .torrent file
mktorrent -l 22 "${name}" \
-a udp://tracker-udp.gbitt.info:80/announce,http://tracker.gbitt.info/announce,https://tracker.gbitt.info/announce \
-a http://retracker.local/announce \
-w "https://planet.openstreetmap.org/${web_path}" \
+ -w "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/${s3_web_path}" \
+ -w "https://osm-planet-us-west-2.s3.dualstack.us-west-2.amazonaws.com/${s3_web_path}" \
-w "https://ftp5.gwdg.de/pub/misc/openstreetmap/planet.openstreetmap.org/${web_path}" \
-w "https://ftpmirror.your.org/pub/openstreetmap/${web_path}" \
-w "https://mirror.init7.net/openstreetmap/${web_path}" \
- -w "https://free.nchc.org.tw/osm.planet/${web_path}" \
-w "https://ftp.fau.de/osm-planet/${web_path}" \
-w "https://ftp.spline.de/pub/openstreetmap/${web_path}" \
- -w "https://osm.openarchive.site/${name}" \
-w "https://downloads.opencagedata.com/planet/${name}" \
-w "https://planet.osm-hr.org/${web_path}" \
-w "https://planet.maps.mail.ru/${web_path}" \
"${rss_file}"
}
+function replication_status_wait {
+ local s3_url="$1"
+ for i in {1..3600}; do
+ local replication_status=$(curl -sI --location "${s3_url}" | grep -F 'x-amz-replication-status' | awk '{print $2}' | tr -d '\r' )
+
+ if [[ "${replication_status}" == "COMPLETED" ]]; then
+ return 0 # success
+ fi
+
+ sleep 1
+ done
+ echo "Timeout waiting for ${s3_url} to complete replication status: ${replication_status}"
+}
+
# Function to install a dump in place
function install_dump {
- type="$1"
- format="$2"
- dir="$3"
- year="$4"
- name="${type}-${date}.osm.${format}"
- latest="${type}-latest.osm.${format}"
- rss_file="${type}-${format}-rss.xml"
+ local type="$1"
+ local format="$2"
+ local dir="$3"
+ local s3dir="$4"
+ local year="$5"
+ local name="${type}-${date}.osm.${format}"
+ local latest="${type}-latest.osm.${format}"
+ local rss_file="${type}-${format}-rss.xml"
md5sum "${name}" > "${name}.md5"
+
+ # Upload all files to S3
+ /opt/awscli/v2/current/bin/aws --profile=osm-pds-upload s3 cp --storage-class=INTELLIGENT_TIERING --no-progress "${name}.md5" "s3://osm-planet-eu-central-1/${s3dir}/${name}.md5"
+ /opt/awscli/v2/current/bin/aws --profile=osm-pds-upload s3 cp --storage-class=INTELLIGENT_TIERING --no-progress "${name}.torrent" "s3://osm-planet-eu-central-1/${s3dir}/${name}.torrent"
+ /opt/awscli/v2/current/bin/aws --profile=osm-pds-upload s3 cp --storage-class=INTELLIGENT_TIERING --no-progress "${name}" "s3://osm-planet-eu-central-1/${s3dir}/${name}"
+
+ # Waiting for S3 replication to complete
+ replication_status_wait "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/${s3dir}/${name}.md5"
+ replication_status_wait "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/${s3dir}/${name}.torrent"
+ replication_status_wait "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/${s3dir}/${name}"
+
mkdir -p "${dir}/${year}"
mv "${name}" "${name}.md5" "${dir}/${year}"
ln -sf "${year:-.}/${name}" "${dir}/${latest}"
}
# Create *.torrent files
-mk_torrent "changesets" "bz2" "planet" "/${year}"
-mk_torrent "discussions" "bz2" "planet" "/${year}"
-mk_torrent "planet" "bz2" "planet" "/${year}"
-mk_torrent "history" "bz2" "planet/full-history" "/${year}"
-mk_torrent "planet" "pbf" "pbf"
-mk_torrent "history" "pbf" "pbf/full-history"
+mk_torrent "changesets" "bz2" "planet" "changesets/osm/${year}" "/${year}"
+mk_torrent "discussions" "bz2" "planet" "discussions/osm/${year}" "/${year}"
+mk_torrent "planet" "bz2" "planet" "planet/osm/${year}" "/${year}"
+mk_torrent "history" "bz2" "planet/full-history" "planet-full-history/osm/${year}" "/${year}"
+mk_torrent "planet" "pbf" "pbf" "planet/pbf/${year}"
+mk_torrent "history" "pbf" "pbf/full-history" "planet-full-history/pbf/${year}"
# Move dumps into place
-install_dump "changesets" "bz2" "<%= node[:planet][:dump][:xml_directory] %>" "${year}"
-install_dump "discussions" "bz2" "<%= node[:planet][:dump][:xml_directory] %>" "${year}"
-install_dump "planet" "bz2" "<%= node[:planet][:dump][:xml_directory] %>" "${year}"
-install_dump "history" "bz2" "<%= node[:planet][:dump][:xml_history_directory] %>" "${year}"
-install_dump "planet" "pbf" "<%= node[:planet][:dump][:pbf_directory] %>"
-install_dump "history" "pbf" "<%= node[:planet][:dump][:pbf_history_directory] %>"
-
-# Remove pbf dumps older than 90 days
-find "<%= node[:planet][:dump][:pbf_directory] %>" "<%= node[:planet][:dump][:pbf_history_directory] %>" \
- -maxdepth 1 -mindepth 1 -type f -mtime +90 \
- \( \
- -iname 'planet-*.pbf' \
- -o -iname 'history-*.pbf' \
- -o -iname 'planet-*.pbf.md5' \
- -o -iname 'history-*.pbf.md5' \
- \) \
- -delete
+install_dump "changesets" "bz2" "<%= node[:planet][:dump][:xml_directory] %>" "changesets/osm/${year}" "${year}"
+install_dump "discussions" "bz2" "<%= node[:planet][:dump][:xml_directory] %>" "discussions/osm/${year}" "${year}"
+install_dump "planet" "bz2" "<%= node[:planet][:dump][:xml_directory] %>" "planet/osm/${year}" "${year}"
+install_dump "history" "bz2" "<%= node[:planet][:dump][:xml_history_directory] %>" "planet-full-history/osm/${year}" "${year}"
+install_dump "planet" "pbf" "<%= node[:planet][:dump][:pbf_directory] %>" "planet/pbf/${year}"
+install_dump "history" "pbf" "<%= node[:planet][:dump][:pbf_history_directory] %>" "planet-full-history/pbf/${year}"
+++ /dev/null
-#!/bin/sh
-
-set -e
-
-cd /etc/replication
-
-osmdbt-catchup --quiet
-osmdbt-get-log --quiet
-osmdbt-catchup --quiet
-osmdbt-create-diff --quiet --with-comment --max-changes=50000
--- /dev/null
+default[:podman][:ports] = {}
-name "munin"
+name "podman"
maintainer "OpenStreetMap Administrators"
maintainer_email "admins@openstreetmap.org"
license "Apache-2.0"
-description "Installs and configures munin"
+description "Installs and configures podman"
version "1.0.0"
supports "ubuntu"
depends "apache"
-depends "networking"
+depends "systemd"
--- /dev/null
+#
+# Cookbook:: podman
+# Recipe:: apache
+#
+# Copyright:: 2023, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "podman"
+include_recipe "apache"
+
+apache_module "proxy_http"
--- /dev/null
+#
+# Cookbook:: podman
+# Recipe:: default
+#
+# Copyright:: 2023, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+package %w[
+ podman
+ slirp4netns
+ uidmap
+ fuse-overlayfs
+]
+
+ruby_block "subuid-containers" do
+ block do
+ File.open("/etc/subuid", "a") do |file|
+ file.puts("containers:2147483647:2147483648")
+ end
+ end
+ not_if "grep -q '^containers:' /etc/subuid"
+end
+
+ruby_block "subgid-containers" do
+ block do
+ File.open("/etc/subgid", "a") do |file|
+ file.puts("containers:2147483647:2147483648")
+ end
+ end
+ not_if "grep -q '^containers:' /etc/subgid"
+end
+
+systemd_timer "podman-auto-update-frequency" do
+ timer "podman-auto-update"
+ dropin "frequency"
+ on_boot_sec "5m"
+ on_unit_inactive_sec "20m"
+ randomized_delay_sec "5m"
+end
+
+service "podman-auto-update.timer" do
+ action [:enable, :start]
+end
--- /dev/null
+#
+# Cookbook:: podman
+# Resource:: podman_service
+#
+# Copyright:: 2023, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+unified_mode true
+
+default_action :create
+
+property :service, String, :name_property => true
+property :description, String, :required => true
+property :image, String, :required => true
+property :ports, Hash
+property :environment, Hash, :default => {}
+property :volume, Hash, :default => {}
+
+action :create do
+ systemd_service new_resource.service do
+ description new_resource.description
+ type "notify"
+ notify_access "all"
+ environment "PODMAN_SYSTEMD_UNIT" => "%n"
+ exec_start_pre "/bin/rm --force %t/%n.ctr-id"
+ exec_start "/usr/bin/podman run --cidfile=%t/%n.ctr-id --cgroups=no-conmon --userns=auto --label=io.containers.autoupdate=registry --pids-limit=-1 #{publish_options} #{environment_options} #{volume_options} --rm --sdnotify=conmon --detach --replace --name=%N #{new_resource.image}"
+ exec_stop "/usr/bin/podman stop --ignore --time=10 --cidfile=%t/%n.ctr-id"
+ exec_stop_post "/usr/bin/podman rm --force --ignore --cidfile=%t/%n.ctr-id"
+ timeout_start_sec 180
+ timeout_stop_sec 70
+ restart "on-failure"
+ end
+
+ # No action :start here to avoid a start and then immediate :restart, due to subscribe, on first run
+ # FIXME: Ubuntu 22.04 podman/crun bug workaround "retries"
+ service new_resource.service do
+ action :enable
+ subscribes :restart, "systemd_service[#{new_resource.service}]", :immediately
+ retries 4 # Workaround https://github.com/containers/podman/issues/9752
+ retry_delay 5
+ end
+
+ # Ensure the service is started if not running, replies on status of service resource
+ notify_group new_resource.service do
+ action :run
+ notifies :start, "service[#{new_resource.service}]", :immediately
+ end
+end
+
+action :delete do
+ service new_resource.service do
+ action [:disable, :stop]
+ end
+
+ systemd_service new_resource.service do
+ action :delete
+ end
+end
+
+action_class do
+ def publish_options
+ new_resource.ports.collect do |host, guest|
+ "--publish=127.0.0.1:#{host}:#{guest}"
+ end.join(" ")
+ end
+
+ def environment_options
+ new_resource.environment.collect do |key, value|
+ "-e '#{key}=#{value}'"
+ end.join(" ")
+ end
+
+ def volume_options
+ new_resource.volume.collect do |key, value|
+ "-v '#{key}:#{value}'"
+ end.join(" ")
+ end
+end
--- /dev/null
+#
+# Cookbook:: podman
+# Resource:: podman_site
+#
+# Copyright:: 2023, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "yaml"
+
+unified_mode true
+
+default_action :create
+
+property :site, String, :name_property => true
+property :image, String, :required => true
+property :port, Integer, :default => 8080
+property :aliases, :kind_of => Array, :default => []
+property :environment, Hash, :default => {}
+
+action :create do
+ podman_service new_resource.site do
+ description "Container service for #{new_resource.site}"
+ image new_resource.image
+ ports external_port => new_resource.port
+ environment new_resource.environment
+ end
+
+ ssl_certificate new_resource.site do
+ domains Array(new_resource.site) + new_resource.aliases
+ end
+
+ apache_site new_resource.site do
+ cookbook "podman"
+ template "apache.erb"
+ variables :port => external_port, :aliases => new_resource.aliases
+ end
+end
+
+action :delete do
+ apache_site new_resource.site do
+ action [:disable, :delete]
+ end
+
+ podman_service new_resource.site do
+ action :delete
+ end
+
+ node.rm_normal(:podman, :ports, new_resource.site)
+end
+
+action_class do
+ def ports_file
+ "#{Chef::Config[:file_cache_path]}/podman-ports.yml"
+ end
+
+ def ports
+ @ports ||= if ::File.exist?(ports_file)
+ YAML.safe_load(::File.read(ports_file))
+ else
+ {}
+ end
+ end
+
+ def external_port
+ unless ports.include?(new_resource.site)
+ port = 40000
+
+ port += 1 while ports.values.include?(port)
+
+ ports[new_resource.site] = port
+
+ ::File.write(ports_file, YAML.dump(ports))
+ end
+
+ ports[new_resource.site]
+ end
+end
+
+def after_created
+ notifies :reload, "service[apache2]"
+end
# DO NOT EDIT - This file is being maintained by Chef
-<VirtualHost *:443>
+<VirtualHost *:80>
ServerName <%= @name %>
+<% @aliases.each do |alias_name| -%>
+ ServerAlias <%= alias_name %>
+<% end -%>
ServerAdmin webmaster@openstreetmap.org
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
- SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
-
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
- DocumentRoot <%= @directory %>
+ RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
+ RedirectPermanent / https://<%= @name %>/
</VirtualHost>
<% unless @aliases.empty? -%>
<% end -%>
ServerAdmin webmaster@openstreetmap.org
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
+ ErrorLog /var/log/apache2/<%= @name %>-error.log
+
SSLEngine on
SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
- ErrorLog /var/log/apache2/<%= @name %>-error.log
-
RedirectPermanent / https://<%= @name %>/
</VirtualHost>
<% end -%>
-<VirtualHost *:80>
+<VirtualHost *:443>
ServerName <%= @name %>
-<% @aliases.each do |alias_name| -%>
- ServerAlias <%= alias_name %>
-<% end -%>
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
- RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
- RedirectPermanent / https://<%= @name %>/
-</VirtualHost>
+ SSLEngine on
+ SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
+ SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
+
+ RequestHeader set X-Forwarded-Proto "https"
+ RequestHeader set X-Forwarded-Port "443"
-<Directory <%= @directory %>>
- Require all granted
-</Directory>
+ ProxyPass / http://localhost:<%= @port %>/
+ ProxyPreserveHost on
+</VirtualHost>
* database: For managing databases.
* execute: For running commands against the database.
* extension: For installing extensions.
-* munin: For configuring munin plugins for a given database name.
* table: For managing database tables.
* user: For managing database users.
* tablespace: For managing tablespaces.
default[:postgresql][:versions] = []
default[:postgresql][:clusters] = {}
-default[:postgresql][:monitor_tables] = true
+default[:postgresql][:monitor_database] = "postgres"
+default[:postgresql][:monitor_queries] = false
default[:postgresql][:settings][:defaults][:port] = "5432"
default[:postgresql][:settings][:defaults][:max_connections] = "100"
default[:postgresql][:settings][:defaults][:ssl] = "true"
-default[:postgresql][:settings][:defaults][:shared_buffers] = "32MB"
+default[:postgresql][:settings][:defaults][:shared_buffers] = "128MB"
default[:postgresql][:settings][:defaults][:temp_buffers] = "8MB"
-default[:postgresql][:settings][:defaults][:work_mem] = "1MB"
-default[:postgresql][:settings][:defaults][:maintenance_work_mem] = "16MB"
+default[:postgresql][:settings][:defaults][:work_mem] = "4MB"
+default[:postgresql][:settings][:defaults][:maintenance_work_mem] = "64MB"
default[:postgresql][:settings][:defaults][:max_stack_depth] = "2MB"
-default[:postgresql][:settings][:defaults][:effective_io_concurrency] = "1"
+default[:postgresql][:settings][:defaults][:effective_io_concurrency] = "256"
default[:postgresql][:settings][:defaults][:max_worker_processes] = "8"
default[:postgresql][:settings][:defaults][:max_parallel_workers_per_gather] = "2"
default[:postgresql][:settings][:defaults][:max_parallel_workers] = "8"
-default[:postgresql][:settings][:defaults][:wal_level] = "minimal"
+default[:postgresql][:settings][:defaults][:wal_level] = "replica"
default[:postgresql][:settings][:defaults][:fsync] = "on"
default[:postgresql][:settings][:defaults][:synchronous_commit] = "on"
default[:postgresql][:settings][:defaults][:wal_buffers] = "-1"
default[:postgresql][:settings][:defaults][:wal_writer_delay] = "200ms"
default[:postgresql][:settings][:defaults][:commit_delay] = "0"
-default[:postgresql][:settings][:defaults][:checkpoint_segments] = "3"
default[:postgresql][:settings][:defaults][:checkpoint_timeout] = "5min"
+default[:postgresql][:settings][:defaults][:checkpoint_completion_target] = "0.9"
default[:postgresql][:settings][:defaults][:max_wal_size] = "1GB"
default[:postgresql][:settings][:defaults][:min_wal_size] = "80MB"
-default[:postgresql][:settings][:defaults][:checkpoint_completion_target] = "0.5"
default[:postgresql][:settings][:defaults][:archive_mode] = "off"
-default[:postgresql][:settings][:defaults][:max_wal_senders] = "0"
-default[:postgresql][:settings][:defaults][:max_replication_slots] = "0"
-default[:postgresql][:settings][:defaults][:hot_standby] = "off"
+default[:postgresql][:settings][:defaults][:max_wal_senders] = "10"
+default[:postgresql][:settings][:defaults][:max_replication_slots] = "10"
+default[:postgresql][:settings][:defaults][:wal_keep_size] = "0"
+default[:postgresql][:settings][:defaults][:hot_standby] = "on"
default[:postgresql][:settings][:defaults][:hot_standby_feedback] = "off"
-default[:postgresql][:settings][:defaults][:random_page_cost] = "4.0"
+default[:postgresql][:settings][:defaults][:seq_page_cost] = "1.0"
+default[:postgresql][:settings][:defaults][:random_page_cost] = "1.1"
default[:postgresql][:settings][:defaults][:cpu_tuple_cost] = "0.01"
-default[:postgresql][:settings][:defaults][:effective_cache_size] = "128MB"
+default[:postgresql][:settings][:defaults][:effective_cache_size] = "4GB"
default[:postgresql][:settings][:defaults][:default_statistics_target] = "100"
default[:postgresql][:settings][:defaults][:jit] = "on"
default[:postgresql][:settings][:defaults][:log_min_duration_statement] = "-1"
-default[:postgresql][:settings][:defaults][:track_activity_query_size] = "1024"
default[:postgresql][:settings][:defaults][:log_autovacuum_min_duration] = "-1"
+default[:postgresql][:settings][:defaults][:track_activity_query_size] = "1024"
default[:postgresql][:settings][:defaults][:autovacuum_max_workers] = "3"
default[:postgresql][:settings][:defaults][:autovacuum_naptime] = "1min"
default[:postgresql][:settings][:defaults][:autovacuum_vacuum_scale_factor] = "0.2"
default[:postgresql][:settings][:defaults][:early_authentication_rules] = []
default[:postgresql][:settings][:defaults][:late_authentication_rules] = []
default[:postgresql][:settings][:defaults][:standby_mode] = "off"
-
-default[:apt][:sources] = node[:apt][:sources] | ["postgresql"]
:select, :insert, :update, :delete, :truncate, :references, :trigger
].freeze
+ SEQUENCE_PRIVILEGES = [
+ :usage, :select, :update
+ ].freeze
+
def initialize(cluster)
@cluster = cluster
end
+ def version
+ @cluster.split("/").first.to_f
+ end
+
def execute(options)
# Create argument array
args = []
end
def users
- @users ||= query("SELECT * FROM pg_user").each_with_object({}) do |user, users|
+ @users ||= query("SELECT *, ARRAY(SELECT groname FROM pg_group WHERE usesysid = ANY(grolist)) AS roles FROM pg_user").each_with_object({}) do |user, users|
users[user[:usename]] = {
:superuser => user[:usesuper] == "t",
:createdb => user[:usercreatedb] == "t",
:createrole => user[:usecatupd] == "t",
- :replication => user[:userepl] == "t"
+ :replication => user[:userepl] == "t",
+ :roles => parse_array(user[:roles] || "{}")
}
end
end
def tables(database)
@tables ||= {}
- @tables[database] ||= query("SELECT n.nspname, c.relname, u.usename, c.relacl FROM pg_class AS c INNER JOIN pg_user AS u ON c.relowner = u.usesysid INNER JOIN pg_namespace AS n ON c.relnamespace = n.oid", :database => database).each_with_object({}) do |table, tables|
+ @tables[database] ||= query("SELECT n.nspname, c.relname, u.usename, c.relacl FROM pg_class AS c INNER JOIN pg_user AS u ON c.relowner = u.usesysid INNER JOIN pg_namespace AS n ON c.relnamespace = n.oid WHERE n.nspname NOT IN ('pg_catalog', 'information_schema') AND c.relkind = 'r'", :database => database).each_with_object({}) do |table, tables|
name = "#{table[:nspname]}.#{table[:relname]}"
tables[name] = {
end
end
+ def sequences(database)
+ @sequences ||= {}
+ @sequences[database] ||= query("SELECT n.nspname, c.relname, u.usename, c.relacl FROM pg_class AS c INNER JOIN pg_user AS u ON c.relowner = u.usesysid INNER JOIN pg_namespace AS n ON c.relnamespace = n.oid WHERE n.nspname NOT IN ('pg_catalog', 'information_schema') AND c.relkind = 'S'", :database => database).each_with_object({}) do |sequence, sequences|
+ name = "#{sequence[:nspname]}.#{sequence[:relname]}"
+
+ sequences[name] = {
+ :owner => sequence[:usename],
+ :permissions => parse_acl(sequence[:relacl] || "{}")
+ }
+ end
+ end
+
private
+ def parse_array(array)
+ array.sub(/^\{(.*)\}$/, "\\1").split(",")
+ end
+
def parse_acl(acl)
- acl.sub(/^\{(.*)\}$/, "\\1").split(",").each_with_object({}) do |entry, permissions|
+ parse_array(acl).each_with_object({}) do |entry, permissions|
entry = entry.sub(/^"(.*)"$/) { Regexp.last_match[1].gsub(/\\"/, '"') }.sub(%r{/.*$}, "")
user, privileges = entry.split("=")
user = "public" if user == ""
permissions[user] = {
- "a" => :insert, "r" => :select, "w" => :update, "d" => :delete,
- "D" => :truncate, "x" => :references, "t" => :trigger
+ "r" => :select, "a" => :insert, "w" => :update, "d" => :delete,
+ "D" => :truncate, "x" => :references, "t" => :trigger,
+ "C" => :create, "c" => :connect, "T" => :temporary,
+ "X" => :execute, "U" => :usage, "s" => :set, "A" => :alter_system
}.values_at(*privileges.chars).compact
end
end
version "1.0.0"
supports "ubuntu"
depends "apt"
-depends "munin"
depends "ohai"
depends "prometheus"
# limitations under the License.
#
-include_recipe "apt"
-include_recipe "munin"
+include_recipe "apt::postgresql"
include_recipe "prometheus"
package "locales-all"
defaults = node[:postgresql][:settings][:defaults] || {}
settings = node[:postgresql][:settings][version] || {}
+ standby_mode = settings[:standby_mode] || defaults[:standby_mode]
+ primary_conninfo = settings[:primary_conninfo] || defaults[:primary_conninfo]
+
+ passwords = if primary_conninfo
+ data_bag_item(primary_conninfo[:passwords][:bag],
+ primary_conninfo[:passwords][:item])
+ end
+
template "/etc/postgresql/#{version}/main/postgresql.conf" do
source "postgresql.conf.erb"
owner "postgres"
group "postgres"
mode "644"
- variables :version => version, :defaults => defaults, :settings => settings
+ variables :version => version,
+ :defaults => defaults,
+ :settings => settings,
+ :primary_conninfo => primary_conninfo,
+ :passwords => passwords
notifies :reload, "service[postgresql]"
+ only_if { ::Dir.exist?("/etc/postgresql/#{version}/main") }
end
template "/etc/postgresql/#{version}/main/pg_hba.conf" do
variables :early_rules => settings[:early_authentication_rules] || defaults[:early_authentication_rules],
:late_rules => settings[:late_authentication_rules] || defaults[:late_authentication_rules]
notifies :reload, "service[postgresql]"
+ only_if { ::Dir.exist?("/etc/postgresql/#{version}/main") }
end
template "/etc/postgresql/#{version}/main/pg_ident.conf" do
mode "640"
variables :maps => settings[:user_name_maps] || defaults[:user_name_maps]
notifies :reload, "service[postgresql]"
+ only_if { ::Dir.exist?("/etc/postgresql/#{version}/main") }
end
link "/var/lib/postgresql/#{version}/main/server.crt" do
to "/etc/ssl/certs/ssl-cert-snakeoil.pem"
+ only_if { ::Dir.exist?("/var/lib/postgresql/#{version}/main") }
end
link "/var/lib/postgresql/#{version}/main/server.key" do
to "/etc/ssl/private/ssl-cert-snakeoil.key"
+ only_if { ::Dir.exist?("/var/lib/postgresql/#{version}/main") }
end
- standby_mode = settings[:standby_mode] || defaults[:standby_mode]
- primary_conninfo = settings[:primary_conninfo] || defaults[:primary_conninfo]
- restore_command = settings[:restore_command] || defaults[:restore_command]
-
- if restore_command || standby_mode == "on"
- passwords = if primary_conninfo
- data_bag_item(primary_conninfo[:passwords][:bag],
- primary_conninfo[:passwords][:item])
- end
-
- template "/var/lib/postgresql/#{version}/main/recovery.conf" do
- source "recovery.conf.erb"
+ if standby_mode == "on"
+ file "/var/lib/postgresql/#{version}/main/standby.signal" do
owner "postgres"
group "postgres"
mode "640"
- variables :standby_mode => standby_mode,
- :primary_conninfo => primary_conninfo,
- :restore_command => restore_command,
- :passwords => passwords
- notifies :reload, "service[postgresql]"
end
else
- template "/var/lib/postgresql/#{version}/main/recovery.conf" do
+ file "/var/lib/postgresql/#{version}/main/standby.signal" do
action :delete
- notifies :reload, "service[postgresql]"
end
end
end
package "libdbd-pg-perl"
clusters = node[:postgresql][:clusters] || []
+passwords = data_bag_item("postgresql", "passwords")
clusters.each do |name, details|
- suffix = name.tr("/", ":")
-
- munin_plugin "postgres_bgwriter_#{suffix}" do
- target "postgres_bgwriter"
- conf "munin.erb"
- conf_variables :port => details[:port]
- end
-
- munin_plugin "postgres_checkpoints_#{suffix}" do
- target "postgres_checkpoints"
- conf "munin.erb"
- conf_variables :port => details[:port]
+ prometheus_suffix = name.tr("/", "-")
+ prometheus_database = node[:postgresql][:monitor_database]
+
+ postgresql_user "prometheus" do
+ cluster name
+ password passwords["prometheus"]
+ roles "pg_monitor"
+ not_if { ::File.exist?("/var/lib/postgresql/#{name}/standby.signal") }
end
- munin_plugin "postgres_connections_db_#{suffix}" do
- target "postgres_connections_db"
- conf "munin.erb"
- conf_variables :port => details[:port]
+ prometheus_exporter "postgres" do
+ port 10000 + details[:port].to_i
+ service "postgres-#{prometheus_suffix}"
+ labels "cluster" => name
+ scrape_interval "1m"
+ scrape_timeout "1m"
+ options %w[
+ --collector.database_wraparound
+ --collector.long_running_transactions
+ --collector.process_idle
+ --collector.stat_activity_autovacuum
+ --collector.stat_wal_receiver
+ --collector.statio_user_indexes
+ ]
+ environment "DATA_SOURCE_NAME" => "postgres:///#{prometheus_database}?host=/run/postgresql&port=#{details[:port]}&user=prometheus&password=#{passwords['prometheus']}"
+ restrict_address_families "AF_UNIX"
+ subscribes :restart, "template[/etc/prometheus/exporters/postgres_queries.yml]"
end
- munin_plugin "postgres_users_#{suffix}" do
- target "postgres_users"
- conf "munin.erb"
- conf_variables :port => details[:port]
- end
-
- munin_plugin "postgres_xlog_#{suffix}" do
- target "postgres_xlog"
- conf "munin.erb"
- conf_variables :port => details[:port]
- end
+ if node[:postgresql][:monitor_queries]
+ template "/etc/prometheus/exporters/sql_exporter.yml" do
+ source "sql_exporter.yml.erb"
+ owner "root"
+ group "root"
+ mode "644"
+ end
- next unless File.exist?("/var/lib/postgresql/#{details[:version]}/main/recovery.conf")
+ prometheus_exporter "sql" do
+ port 20000 + details[:port].to_i
+ service "sql-#{prometheus_suffix}"
+ labels "cluster" => name
+ scrape_interval "1m"
+ scrape_timeout "1m"
+ options "--config.file=/etc/prometheus/exporters/sql_exporter.yml"
+ environment "SQLEXPORTER_TARGET_DSN" => "postgres://prometheus:#{passwords['prometheus']}@/run/postgresql:#{details[:port]}/#{prometheus_database}"
+ restrict_address_families "AF_UNIX"
+ subscribes :restart, "template[/etc/prometheus/exporters/sql_exporter.yml]"
+ end
+ else
+ prometheus_exporter "sql" do
+ action :delete
+ service "sql-#{prometheus_suffix}"
+ end
- munin_plugin "postgres_replication_#{suffix}" do
- target "postgres_replication"
- conf "munin.erb"
- conf_variables :port => details[:port]
+ file "/etc/prometheus/exporters/sql_exporter.yml" do
+ action :delete
+ end
end
end
-
-uris = clusters.collect do |_, details|
- "postgres@:#{details[:port]}/postgres?host=/run/postgresql"
-end
-
-template "/etc/prometheus/exporters/postgres_queries.yml" do
- source "postgres_queries.yml.erb"
- owner "root"
- group "root"
- mode "644"
-end
-
-prometheus_exporter "postgres" do
- port 9187
- user "postgres"
- options "--extend.query-path=/etc/prometheus/exporters/postgres_queries.yml"
- environment "DATA_SOURCE_URI" => uris.sort.uniq.first,
- "PG_EXPORTER_AUTO_DISCOVER_DATABASES" => "true",
- "PG_EXPORTER_EXCLUDE_DATABASES" => "postgres,template0,template1"
- subscribes :restart, "template[/etc/prometheus/exporters/postgres_queries.yml]"
-end
action :drop do
if cluster.databases.include?(new_resource.database)
converge_by "drop database #{new_resource.database}" do
- cluster.execute(:command => "DROP DATABASE \"#{new_resource.database}\"")
+ if cluster.version >= 13
+ cluster.execute(:command => "DROP DATABASE \"#{new_resource.database}\" WITH (FORCE)")
+ else
+ cluster.execute(:command => "DROP DATABASE \"#{new_resource.database}\"")
+ end
end
end
end
+++ /dev/null
-#
-# Cookbook:: postgresql
-# Resource:: postgresql_munin
-#
-# Copyright:: 2015, OpenStreetMap Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-unified_mode true
-
-default_action :create
-
-property :munin, :kind_of => String, :name_property => true
-property :cluster, :kind_of => String, :required => true
-property :database, :kind_of => String, :required => true
-
-action :create do
- cluster = node[:postgresql][:clusters] && node[:postgresql][:clusters][new_resource.cluster]
- database = new_resource.database
-
- if cluster
- %w[cache connections locks querylength scans size transactions tuples].each do |plugin|
- munin_plugin "postgres_#{plugin}_#{database}:#{suffix}" do
- target "postgres_#{plugin}_"
- conf "munin.erb"
- conf_cookbook "postgresql"
- conf_variables :port => cluster[:port]
- restart_munin false
- end
- end
- else
- Chef::Log.info "Postgres cluster #{new_resource.cluster} not found"
- end
-end
-
-action :delete do
- database = new_resource.database
-
- %w[cache connections locks querylength scans size transactions tuples].each do |plugin|
- munin_plugin "postgres_#{plugin}_#{database}:#{suffix}" do
- action :delete
- restart_munin false
- end
- end
-end
-
-action_class do
- def suffix
- new_resource.cluster.tr("/", ":")
- end
-end
-
-def after_created
- notifies :restart, "service[munin-node]"
-end
--- /dev/null
+#
+# Cookbook:: postgresql
+# Resource:: postgresql_sequence
+#
+# Copyright:: 2023, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+unified_mode true
+
+default_action :create
+
+property :sequence, :kind_of => String, :name_property => true
+property :cluster, :kind_of => String, :required => true
+property :database, :kind_of => String, :required => true
+property :schema, :kind_of => String, :default => "public"
+property :owner, :kind_of => String, :required => [:create]
+property :permissions, :kind_of => Hash, :default => {}
+
+action :create do
+ if sequences.include?(qualified_name)
+ if new_resource.owner != sequences[qualified_name][:owner]
+ converge_by("set owner for #{new_resource} to #{new_resource.owner}") do
+ Chef::Log.info("Setting owner for #{new_resource} to #{new_resource.owner}")
+ cluster.execute(:command => "ALTER SEQUENCE #{qualified_name} OWNER TO \"#{new_resource.owner}\"", :database => new_resource.database)
+ end
+ end
+
+ sequences[qualified_name][:permissions].each_key do |user|
+ next if new_resource.permissions[user]
+
+ converge_by("revoke all for #{user} on #{new_resource}") do
+ Chef::Log.info("Revoking all for #{user} on #{new_resource}")
+ cluster.execute(:command => "REVOKE ALL ON TABLE #{qualified_name} FROM \"#{user}\"", :database => new_resource.database)
+ end
+ end
+
+ new_resource.permissions.each do |user, new_privileges|
+ current_privileges = sequences[qualified_name][:permissions][user] || {}
+ new_privileges = Array(new_privileges)
+
+ if new_privileges.include?(:all)
+ new_privileges |= OpenStreetMap::PostgreSQL::SEQUENCE_PRIVILEGES
+ end
+
+ OpenStreetMap::PostgreSQL::SEQUENCE_PRIVILEGES.each do |privilege|
+ if new_privileges.include?(privilege)
+ unless current_privileges.include?(privilege)
+ converge_by("grant #{privilege} for #{user} on #{new_resource}") do
+ Chef::Log.info("Granting #{privilege} for #{user} on #{new_resource}")
+ cluster.execute(:command => "GRANT #{privilege.to_s.upcase} ON SEQUENCE #{qualified_name} TO \"#{user}\"", :database => new_resource.database)
+ end
+ end
+ elsif current_privileges.include?(privilege)
+ converge_by("revoke #{privilege} for #{user} on #{new_resource}") do
+ Chef::Log.info("Revoking #{privilege} for #{user} on #{new_resource}")
+ cluster.execute(:command => "REVOKE #{privilege.to_s.upcase} ON SEQUENCE #{qualified_name} FROM \"#{user}\"", :database => new_resource.database)
+ end
+ end
+ end
+ end
+ end
+end
+
+action :drop do
+ if sequences.include?(qualified_name)
+ converge_by("drop #{new_resource}") do
+ Chef::Log.info("Dropping #{new_resource}")
+ cluster.execute(:command => "DROP SEQUENCE #{qualified_name}", :database => new_resource.database)
+ end
+ end
+end
+
+action_class do
+ def cluster
+ @cluster ||= OpenStreetMap::PostgreSQL.new(new_resource.cluster)
+ end
+
+ def sequences
+ @sequences ||= cluster.sequences(new_resource.database)
+ end
+
+ def qualified_name
+ "#{new_resource.schema}.#{new_resource.name}"
+ end
+end
converge_by("revoke all for #{user} on #{new_resource}") do
Chef::Log.info("Revoking all for #{user} on #{new_resource}")
- cluster.execute(:command => "REVOKE ALL ON #{qualified_name} FROM \"#{user}\"", :database => new_resource.database)
+ cluster.execute(:command => "REVOKE ALL ON TABLE #{qualified_name} FROM \"#{user}\"", :database => new_resource.database)
end
end
unless current_privileges.include?(privilege)
converge_by("grant #{privilege} for #{user} on #{new_resource}") do
Chef::Log.info("Granting #{privilege} for #{user} on #{new_resource}")
- cluster.execute(:command => "GRANT #{privilege.to_s.upcase} ON #{qualified_name} TO \"#{user}\"", :database => new_resource.database)
+ cluster.execute(:command => "GRANT #{privilege.to_s.upcase} ON TABLE #{qualified_name} TO \"#{user}\"", :database => new_resource.database)
end
end
elsif current_privileges.include?(privilege)
converge_by("revoke #{privilege} for #{user} on #{new_resource}") do
Chef::Log.info("Revoking #{privilege} for #{user} on #{new_resource}")
- cluster.execute(:command => "REVOKE #{privilege.to_s.upcase} ON #{qualified_name} FROM \"#{user}\"", :database => new_resource.database)
+ cluster.execute(:command => "REVOKE #{privilege.to_s.upcase} ON TABLE #{qualified_name} FROM \"#{user}\"", :database => new_resource.database)
end
end
end
property :createdb, :kind_of => [TrueClass, FalseClass], :default => false
property :createrole, :kind_of => [TrueClass, FalseClass], :default => false
property :replication, :kind_of => [TrueClass, FalseClass], :default => false
+property :roles, :kind_of => [String, Array]
action :create do
password = new_resource.password ? "ENCRYPTED PASSWORD '#{new_resource.password.shellescape}'" : ""
converge_by "create role #{new_resource.user}" do
cluster.execute(:command => "CREATE ROLE \"#{new_resource.user}\" LOGIN #{password} #{superuser} #{createdb} #{createrole}")
end
+
+ Array(new_resource.roles).each do |role|
+ converge_by "grant #{role} to #{new_resource.user}" do
+ cluster.execute(:command => "GRANT \"#{role}\" TO \"#{new_resource.user}\"")
+ end
+ end
else
current_user = cluster.users[new_resource.user]
end
end
end
+
+ roles = Array(new_resource.roles)
+
+ roles.each do |role|
+ next if current_user[:roles].include?(role)
+
+ converge_by "grant #{role} to #{new_resource.user}" do
+ cluster.execute(:command => "GRANT \"#{role}\" TO \"#{new_resource.user}\"")
+ end
+ end
+
+ current_user[:roles].each do |role|
+ next if roles.include?(role)
+
+ converge_by "revoke #{role} from #{new_resource.user}" do
+ cluster.execute(:command => "REVOKE \"#{role}\" FROM \"#{new_resource.user}\"")
+ end
+ end
end
end
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-[<%= @name %>]
-user postgres
-env.PGUSER postgres
-env.PGPORT <%= @port %>
<% @early_rules.each do |rule| -%>
<%= rule[:type] || "host" %> <%= rule[:database] || "all" %> <%= rule[:user] || "all" %> <%= rule[:address] %> <%= rule[:method] || "md5" %> <%= (rule[:options] || {}).collect { |k,v| "#{k}=#{v}" }.join(" ") %>
<% end -%>
+local all prometheus md5
local all all peer
host all all 127.0.0.1/32 md5
host all all ::1/128 md5
+++ /dev/null
-pg_replication:
- query: "SELECT EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp())) AS lag_seconds"
- master: true
- metrics:
- - lag_seconds:
- usage: "GAUGE"
- description: "Replication lag behind master in seconds"
-
-pg_postmaster:
- query: "SELECT pg_postmaster_start_time as start_time_seconds from pg_postmaster_start_time()"
- master: true
- metrics:
- - start_time_seconds:
- usage: "GAUGE"
- description: "Time at which postmaster started"
-<% if node[:postgresql][:monitor_tables] -%>
-
-pg_stat_user_tables:
- query: "SELECT current_database() datname, schemaname, relname, seq_scan, seq_tup_read, idx_scan, idx_tup_fetch, n_tup_ins, n_tup_upd, n_tup_del, n_tup_hot_upd, n_live_tup, n_dead_tup, n_mod_since_analyze, COALESCE(last_vacuum, '1970-01-01Z'), COALESCE(last_vacuum, '1970-01-01Z') as last_vacuum, COALESCE(last_autovacuum, '1970-01-01Z') as last_autovacuum, COALESCE(last_analyze, '1970-01-01Z') as last_analyze, COALESCE(last_autoanalyze, '1970-01-01Z') as last_autoanalyze, vacuum_count, autovacuum_count, analyze_count, autoanalyze_count FROM pg_stat_user_tables"
- metrics:
- - datname:
- usage: "LABEL"
- description: "Name of current database"
- - schemaname:
- usage: "LABEL"
- description: "Name of the schema that this table is in"
- - relname:
- usage: "LABEL"
- description: "Name of this table"
- - seq_scan:
- usage: "COUNTER"
- description: "Number of sequential scans initiated on this table"
- - seq_tup_read:
- usage: "COUNTER"
- description: "Number of live rows fetched by sequential scans"
- - idx_scan:
- usage: "COUNTER"
- description: "Number of index scans initiated on this table"
- - idx_tup_fetch:
- usage: "COUNTER"
- description: "Number of live rows fetched by index scans"
- - n_tup_ins:
- usage: "COUNTER"
- description: "Number of rows inserted"
- - n_tup_upd:
- usage: "COUNTER"
- description: "Number of rows updated"
- - n_tup_del:
- usage: "COUNTER"
- description: "Number of rows deleted"
- - n_tup_hot_upd:
- usage: "COUNTER"
- description: "Number of rows HOT updated (i.e., with no separate index update required)"
- - n_live_tup:
- usage: "GAUGE"
- description: "Estimated number of live rows"
- - n_dead_tup:
- usage: "GAUGE"
- description: "Estimated number of dead rows"
- - n_mod_since_analyze:
- usage: "GAUGE"
- description: "Estimated number of rows changed since last analyze"
- - last_vacuum:
- usage: "GAUGE"
- description: "Last time at which this table was manually vacuumed (not counting VACUUM FULL)"
- - last_autovacuum:
- usage: "GAUGE"
- description: "Last time at which this table was vacuumed by the autovacuum daemon"
- - last_analyze:
- usage: "GAUGE"
- description: "Last time at which this table was manually analyzed"
- - last_autoanalyze:
- usage: "GAUGE"
- description: "Last time at which this table was analyzed by the autovacuum daemon"
- - vacuum_count:
- usage: "COUNTER"
- description: "Number of times this table has been manually vacuumed (not counting VACUUM FULL)"
- - autovacuum_count:
- usage: "COUNTER"
- description: "Number of times this table has been vacuumed by the autovacuum daemon"
- - analyze_count:
- usage: "COUNTER"
- description: "Number of times this table has been manually analyzed"
- - autoanalyze_count:
- usage: "COUNTER"
- description: "Number of times this table has been analyzed by the autovacuum daemon"
-
-pg_statio_user_tables:
- query: "SELECT current_database() datname, schemaname, relname, heap_blks_read, heap_blks_hit, idx_blks_read, idx_blks_hit, toast_blks_read, toast_blks_hit, tidx_blks_read, tidx_blks_hit FROM pg_statio_user_tables"
- metrics:
- - datname:
- usage: "LABEL"
- description: "Name of current database"
- - schemaname:
- usage: "LABEL"
- description: "Name of the schema that this table is in"
- - relname:
- usage: "LABEL"
- description: "Name of this table"
- - heap_blks_read:
- usage: "COUNTER"
- description: "Number of disk blocks read from this table"
- - heap_blks_hit:
- usage: "COUNTER"
- description: "Number of buffer hits in this table"
- - idx_blks_read:
- usage: "COUNTER"
- description: "Number of disk blocks read from all indexes on this table"
- - idx_blks_hit:
- usage: "COUNTER"
- description: "Number of buffer hits in all indexes on this table"
- - toast_blks_read:
- usage: "COUNTER"
- description: "Number of disk blocks read from this table's TOAST table (if any)"
- - toast_blks_hit:
- usage: "COUNTER"
- description: "Number of buffer hits in this table's TOAST table (if any)"
- - tidx_blks_read:
- usage: "COUNTER"
- description: "Number of disk blocks read from this table's TOAST table indexes (if any)"
- - tidx_blks_hit:
- usage: "COUNTER"
- description: "Number of buffer hits in this table's TOAST table indexes (if any)"
-<% end -%>
-
-pg_database:
- query: "SELECT pg_database.oid AS datid, pg_database.datname, pg_database_size(pg_database.datname) AS size_bytes FROM pg_database"
- master: true
- cache_seconds: 30
- metrics:
- - datid:
- usage: "LABEL"
- description: "ID of the database"
- - datname:
- usage: "LABEL"
- description: "Name of the database"
- - size_bytes:
- usage: "GAUGE"
- description: "Disk space used by the database"
-
-pg_unfrozen_ids:
- query: "SELECT current_database() AS datname, max(age(relfrozenxid)) AS xid_age, max(mxid_age(relminmxid)) AS mxid_age FROM pg_class WHERE relkind IN ('r', 'm')"
- metrics:
- - datname:
- usage: "LABEL"
- description: "Name of the database"
- - xid_age:
- usage: "GAUGE"
- description: "Age of the oldest unfrozen transaction ID in this database"
- - mxid_age:
- usage: "GAUGE"
- description: "Age of the oldest unfrozen multixact ID in this database"
<% end -%>
port = <%= @settings[:port] || @defaults[:port] %>
max_connections = <%= @settings[:max_connections] || @defaults[:max_connections] %>
-<% if @version.to_f >= 9.3 %>
unix_socket_directories = '/var/run/postgresql'
-<% else -%>
-unix_socket_directory = '/var/run/postgresql'
-<% end -%>
# - Security and Authentication -
effective_io_concurrency = <%= @settings[:effective_io_concurrency] || @defaults[:effective_io_concurrency] %>
max_worker_processes = <%= @settings[:max_worker_processes] || @defaults[:max_worker_processes] %>
-<% if @version.to_f >= 9.6 -%>
max_parallel_workers_per_gather = <%= @settings[:max_parallel_workers_per_gather] || @defaults[:max_parallel_workers_per_gather] %>
-<% end -%>
-<% if @version.to_f >= 10 -%>
max_parallel_workers = <%= @settings[:max_parallel_workers] || @defaults[:max_parallel_workers] %>
-<% end -%>
#------------------------------------------------------------------------------
# WRITE AHEAD LOG
# - Checkpoints -
-<% if @version.to_f < 9.5 -%>
-checkpoint_segments = <%= @settings[:checkpoint_segments] || @defaults[:checkpoint_segments] %>
-<% end -%>
checkpoint_timeout = <%= @settings[:checkpoint_timeout] || @defaults[:checkpoint_timeout] %>
-<% if @version.to_f >= 9.5 -%>
+checkpoint_completion_target = <%= @settings[:checkpoint_completion_target] || @defaults[:checkpoint_completion_target] %>
max_wal_size = <%= @settings[:max_wal_size] || @defaults[:max_wal_size] %>
min_wal_size = <%= @settings[:min_wal_size] || @defaults[:min_wal_size] %>
-<% end -%>
-checkpoint_completion_target = <%= @settings[:checkpoint_completion_target] || @defaults[:checkpoint_completion_target] %>
# - Archiving -
archive_command = '<%= @settings[:archive_command] || @defaults[:archive_command] %>'
<% end -%>
+# - Archive Recovery -
+
+# These are only used in recovery mode.
+
+<% if @settings[:restore_command] || @defaults[:restore_command] -%>
+restore_command = '<%= @settings[:restore_command] || @defaults[:restore_command] %>'
+<% end -%>
+
#------------------------------------------------------------------------------
# REPLICATION
#------------------------------------------------------------------------------
# - Sending Server(s) -
max_wal_senders = <%= @settings[:max_wal_senders] || @defaults[:max_wal_senders] %>
-<% if @version.to_f >= 9.4 -%>
max_replication_slots = <%= @settings[:max_replication_slots] || @defaults[:max_replication_slots] %>
-<% end -%>
+wal_keep_size = <%= @settings[:wal_keep_size] || @defaults[:wal_keep_size] %>
# - Standby Servers -
+<% if @primary_conninfo -%>
+primary_conninfo = 'host=<%= @primary_conninfo[:host] %> port=<%= @primary_conninfo[:port] %> user=<%= @primary_conninfo[:user] %> password=<%= @passwords[@primary_conninfo[:user]] %>'
+<% end -%>
hot_standby = <%= @settings[:hot_standby] || @defaults[:hot_standby] %>
hot_standby_feedback = <%= @settings[:hot_standby_feedback] || @defaults[:hot_standby_feedback] %>
# - Planner Cost Constants -
+seq_page_cost = <%= @settings[:seq_page_cost] || @defaults[:seq_page_cost] %>
random_page_cost = <%= @settings[:random_page_cost] || @defaults[:random_page_cost] %>
cpu_tuple_cost = <%= @settings[:cpu_tuple_cost] || @defaults[:cpu_tuple_cost] %>
effective_cache_size = <%= @settings[:effective_cache_size] || @defaults[:effective_cache_size] %>
# - Other Planner Options -
default_statistics_target = <%= @settings[:default_statistics_target] || @defaults[:default_statistics_target] %>
-<% if @version.to_f >= 12 -%>
jit = <%= @settings[:jit] || @defaults[:jit] %>
-<% end -%>
#------------------------------------------------------------------------------
# REPORTING AND LOGGING
# - What to Log -
+log_autovacuum_min_duration = <%= @settings[:log_autovacuum_min_duration] || @defaults[:log_autovacuum_min_duration] %>
log_line_prefix = '%t '
#------------------------------------------------------------------------------
# - Query/Index Statistics Collector -
track_activity_query_size = <%= @settings[:track_activity_query_size] || @defaults[:track_activity_query_size] %>
+<% if @version.to_f < 15 -%>
stats_temp_directory = '/run/postgresql/<%= @version %>-main.pg_stat_tmp'
+<% end -%>
#------------------------------------------------------------------------------
# AUTOVACUUM PARAMETERS
#------------------------------------------------------------------------------
-log_autovacuum_min_duration = <%= @settings[:log_autovacuum_min_duration] || @defaults[:log_autovacuum_min_duration] %>
autovacuum_max_workers = <%= @settings[:autovacuum_max_workers] || @defaults[:autovacuum_max_workers] %>
autovacuum_naptime = <%= @settings[:autovacuum_naptime] || @defaults[:autovacuum_naptime] %>
autovacuum_vacuum_scale_factor = <%= @settings[:autovacuum_vacuum_scale_factor] || @defaults[:autovacuum_vacuum_scale_factor] %>
--- /dev/null
+# Global defaults.
+global:
+ # If scrape_timeout <= 0, no timeout is set unless Prometheus provides one. The default is 10s.
+ scrape_timeout: 10s
+ # Subtracted from Prometheus' scrape_timeout to give us some headroom and prevent Prometheus from timing out first.
+ scrape_timeout_offset: 500ms
+ # Minimum interval between collector runs: by default (0s) collectors are executed on every scrape.
+ min_interval: 0s
+ # Maximum number of open connections to any one target. Metric queries will run concurrently on multiple connections,
+ # as will concurrent scrapes.
+ max_connections: 3
+ # Maximum number of idle connections to any one target. Unless you use very long collection intervals, this should
+ # always be the same as max_connections.
+ max_idle_connections: 3
+ # Maximum number of maximum amount of time a connection may be reused. Expired connections may be closed lazily before reuse.
+ # If 0, connections are not closed due to a connection's age.
+ max_connection_lifetime: 5m
+
+# The target to monitor and the collectors to execute on it.
+target:
+ # Data source name always has a URI schema that matches the driver name. In some cases (e.g. MySQL)
+ # the schema gets dropped or replaced to match the driver expected DSN format.
+ data_source_name: postgres
+
+ # Collectors (referenced by name) to execute on the target.
+ # Glob patterns are supported (see <https://pkg.go.dev/path/filepath#Match> for syntax).
+ collectors: [sql_*]
+
+# Collector files specifies a list of globs. One collector definition is read from each matching file.
+# Glob patterns are supported (see <https://pkg.go.dev/path/filepath#Match> for syntax).
+collector_files:
+ - "sql_*.collector.yml"
default[:prometheus][:addresses] = {}
default[:prometheus][:exporters] = {}
+default[:prometheus][:junos] = {}
default[:prometheus][:snmp] = {}
-
-if node[:recipes].include?("prometheus::server")
- default[:apt][:sources] |= ["grafana"]
-end
+default[:prometheus][:metrics] = {}
+default[:prometheus][:files] = []
--- /dev/null
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCwBRhz6gJsBcf5xf1WWEdhm6DjOnVlB5CHn48qEDYk4Gy5j62ZsKq+pBmHIJ1SeoR2ezlsMgKyPouzRkIQgh3Mc1qcy0fmr/szsDwhswKjODyk7vfnkEH5bK70W2/WrrBmBi1RGp03hCnJqWFG5uLaYiO2MjkyihTSoLM4XWj71aohbmOhIQiHB8td24JS+3tsGqNe+UhtKWjk2BJ0lqIhDvpOmuLjxGPMVGzBaC4a18jMYFxZs1AxXf/veLP5cduxA7KxT5nWnun2QsW/P0AThBGkhTny/a2GdmQ/aKAmYftFwnBUtgJtGuo/GXkd5Up8BienJzbZ16HhKFl23cXAuFIV7EJwu8bClzCJQtMUE+7rhAX9StDris1P9e1ldjalUSFBMzPHkhf3nHAju3E14URH8DrnfA8kNrnYvYwCgeH3mAu+yht/6mzZWkoaF94AkJVCQ8KRxsuUO9tZO/hLONMuG5FCao1dofnNtvc797XYWS4X6pjBMW5BpANrFrk= prometheus@openstreetmap.org
supports "ubuntu"
depends "apache"
depends "apt"
+depends "awscli"
depends "git"
depends "hardware"
depends "networking"
-depends "timescaledb"
directory "/opt/prometheus" do
action :delete
- owner "root"
- group "root"
- mode "755"
recursive true
- not_if { ::Dir.exist?("/opt/prometheus/.git") }
end
-git "/opt/prometheus" do
+git "/opt/prometheus-exporters" do
action :sync
repository "https://github.com/openstreetmap/prometheus-exporters.git"
revision "main"
prometheus_exporter "node" do
port 9100
+ user "root"
+ proc_subset "all"
+ protect_clock false
+ restrict_address_families %w[AF_UNIX AF_NETLINK]
+ system_call_filter ["@system-service", "@clock"]
options %w[
--collector.textfile.directory=/var/lib/prometheus/node-exporter
--collector.interrupts
- --collector.ntp
--collector.processes
+ --collector.rapl.enable-zone-label
--collector.systemd
--collector.tcpstat
]
metric_relabel metric_relabel
end
+unless node[:prometheus][:junos].empty?
+ targets = node[:prometheus][:junos].collect { |_, details| details[:address] }.sort.join(",")
+
+ prometheus_exporter "junos" do
+ port 9326
+ options %W[
+ --ssh.user=prometheus
+ --ssh.keyfile=/var/lib/prometheus/junos-exporter/id_rsa
+ --ssh.targets=#{targets}
+ --bgp.enabled=false
+ --lacp.enabled=true
+ --ldp.enabled=false
+ --ospf.enabled=false
+ --power.enabled=false
+ ]
+ ssh true
+ register_target false
+ end
+end
+
unless node[:prometheus][:snmp].empty?
prometheus_exporter "snmp" do
port 9116
- options "--config.file=/opt/prometheus/exporters/snmp/snmp.yml"
+ options "--config.file=/opt/prometheus-exporters/exporters/snmp/snmp.yml"
register_target false
end
end
+
+if node[:prometheus][:files].empty?
+ prometheus_exporter "filestat" do
+ action :delete
+ end
+
+ file "/etc/prometheus/filestat.yml" do
+ action :delete
+ end
+else
+ template "/etc/prometheus/filestat.yml" do
+ source "filestat.yml.erb"
+ owner "root"
+ group "root"
+ mode "644"
+ end
+
+ prometheus_exporter "filestat" do
+ port 9943
+ options "--config.file=/etc/prometheus/filestat.yml"
+ subscribes :restart, "template[/etc/prometheus/filestat.yml]"
+ end
+end
#
include_recipe "apache"
-include_recipe "apt"
+include_recipe "apt::grafana"
+include_recipe "awscli"
include_recipe "networking"
-include_recipe "timescaledb"
passwords = data_bag_item("prometheus", "passwords")
tokens = data_bag_item("prometheus", "tokens")
+admins = data_bag_item("apache", "admins")
prometheus_exporter "fastly" do
port 8080
- listen_switch "endpoint"
- listen_type "url"
+ listen_switch "listen"
environment "FASTLY_API_TOKEN" => tokens["fastly"]
end
-package %w[
- prometheus
- prometheus-alertmanager
-]
-
-promscale_version = "0.3.0"
+prometheus_exporter "fastly_healthcheck" do
+ port 9696
+ scrape_interval "1m"
+ environment "FASTLY_API_TOKEN" => tokens["fastly"]
+end
-database_cluster = "#{node[:timescaledb][:database_version]}/main"
+prometheus_exporter "statuscake" do
+ port 9595
+ scrape_interval "5m"
+ scrape_timeout "2m"
+ environment "STATUSCAKE_APIKEY" => tokens["statuscake"]
+end
-postgresql_user "prometheus" do
- cluster database_cluster
- superuser true
+template "/etc/prometheus/cloudwatch.yml" do
+ source "cloudwatch.yml.erb"
+ owner "root"
+ group "root"
+ mode "644"
end
-postgresql_database "promscale" do
- cluster database_cluster
- owner "prometheus"
+prometheus_exporter "cloudwatch" do
+ address "127.0.0.1"
+ port 5000
+ listen_switch "listen-address"
+ options %w[
+ --config.file=/etc/prometheus/cloudwatch.yml
+ --enable-feature=aws-sdk-v2
+ --enable-feature=always-return-info-metrics
+ ]
+ environment "AWS_ACCESS_KEY_ID" => "AKIASQUXHPE7JHG37EA6",
+ "AWS_SECRET_ACCESS_KEY" => tokens["cloudwatch"]
+ subscribes :restart, "template[/etc/prometheus/cloudwatch.yml]"
end
-directory "/opt/promscale" do
+cache_dir = Chef::Config[:file_cache_path]
+
+prometheus_version = "2.45.0"
+alertmanager_version = "0.25.0"
+karma_version = "0.114"
+
+directory "/opt/prometheus-server" do
owner "root"
group "root"
mode "755"
end
-package %w[
- make
- gcc
- clang-9
- llvm-9
- cargo
-]
+prometheus_arch = if arm?
+ "arm64"
+ else
+ "amd64"
+ end
-git "/opt/promscale/extension" do
- action :sync
- repository "https://github.com/timescale/promscale_extension.git"
- revision "0.1.1"
- user "root"
+remote_file "#{cache_dir}/prometheus.linux.tar.gz" do
+ source "https://github.com/prometheus/prometheus/releases/download/v#{prometheus_version}/prometheus-#{prometheus_version}.linux-#{prometheus_arch}.tar.gz"
+ owner "root"
group "root"
+ mode "644"
+ backup false
end
-execute "/opt/promscale/extension/Makefile" do
+archive_file "#{cache_dir}/prometheus.linux.tar.gz" do
action :nothing
- command "make install"
- cwd "/opt/promscale/extension"
- user "root"
+ destination "/opt/prometheus-server/prometheus"
+ overwrite true
+ strip_components 1
+ owner "root"
group "root"
- subscribes :run, "git[/opt/promscale/extension]", :immediately
- notifies :restart, "service[postgresql]", :immediately
+ subscribes :extract, "remote_file[#{cache_dir}/prometheus.linux.tar.gz]", :immediately
end
-directory "/opt/promscale/bin" do
+remote_file "#{cache_dir}/alertmanager.linux.tar.gz" do
+ source "https://github.com/prometheus/alertmanager/releases/download/v#{alertmanager_version}/alertmanager-#{alertmanager_version}.linux-#{prometheus_arch}.tar.gz"
owner "root"
group "root"
- mode "755"
+ mode "644"
+ backup false
end
-remote_file "/opt/promscale/bin/promscale" do
- action :create
- source "https://github.com/timescale/promscale/releases/download/#{promscale_version}/promscale_#{promscale_version}_Linux_x86_64"
+archive_file "#{cache_dir}/alertmanager.linux.tar.gz" do
+ action :nothing
+ destination "/opt/prometheus-server/alertmanager"
+ overwrite true
+ strip_components 1
owner "root"
group "root"
- mode "755"
-end
-
-systemd_service "promscale" do
- description "Promscale Connector"
- type "simple"
- user "prometheus"
- exec_start "/opt/promscale/bin/promscale --db-host /run/postgresql --db-port 5432 --db-user prometheus --db-name promscale --db-connections-max 400"
- # exec_start lazy { "/opt/promscale/bin/promscale --db-host /run/postgresql --db-port #{node[:postgresql][:clusters][database_cluster][:port]} --db-user prometheus --db-name promscale --db-max-connections 400" }
- limit_nofile 16384
- private_tmp true
- protect_system "strict"
- protect_home true
- no_new_privileges true
+ subscribes :extract, "remote_file[#{cache_dir}/alertmanager.linux.tar.gz]", :immediately
end
-service "promscale" do
- action [:enable, :start]
- subscribes :restart, "remote_file[/opt/promscale/bin/promscale]"
- subscribes :restart, "systemd_service[promscale]"
-end
-
-systemd_service "promscale-maintenance" do
- description "Promscale Maintenace"
- type "simple"
- user "prometheus"
- exec_start "/usr/bin/psql --command='CALL prom_api.execute_maintenance()' promscale"
- private_tmp true
- protect_system "strict"
- protect_home true
- no_new_privileges true
-end
-
-systemd_timer "promscale-maintenance" do
- description "Promscale Maintenace"
- on_active_sec 1800
- on_unit_inactive_sec 1800
+remote_file "#{cache_dir}/karma-linux.tar.gz" do
+ source "https://github.com/prymitive/karma/releases/download/v#{karma_version}/karma-linux-#{prometheus_arch}.tar.gz"
+ owner "root"
+ group "root"
+ mode "644"
+ backup false
end
-service "promscale-maintenance.timer" do
- action [:enable, :start]
+archive_file "#{cache_dir}/karma-linux.tar.gz" do
+ action :nothing
+ destination "/opt/prometheus-server/karma"
+ overwrite true
+ owner "root"
+ group "root"
+ subscribes :extract, "remote_file[#{cache_dir}/karma-linux.tar.gz]", :immediately
end
search(:node, "roles:gateway") do |gateway|
- allowed_ips = gateway.interfaces(:role => :internal).map do |interface|
- "#{interface[:network]}/#{interface[:prefix]}"
- end
+ allowed_ips = gateway.ipaddresses(:role => :internal).map(&:subnet)
node.default[:networking][:wireguard][:peers] << {
:public_key => gateway[:networking][:wireguard][:public_key],
end
jobs = {}
+junos_targets = []
snmp_targets = []
search(:node, "recipes:prometheus\\:\\:default").sort_by(&:name).each do |client|
if exporter.is_a?(Hash)
name = exporter[:name]
address = exporter[:address]
+ sni = exporter[:sni]
+ labels = Array(exporter[:labels])
+ scrape_interval = exporter[:scrape_interval]
+ scrape_timeout = exporter[:scrape_timeout]
metric_relabel = exporter[:metric_relabel] || []
else
name = key
address = exporter
+ sni = nil
+ labels = []
+ scrape_interval = nil
+ scrape_timeout = nil
metric_relabel = []
end
jobs[name] ||= []
jobs[name] << {
:address => address,
+ :sni => sni,
:instance => client.name.split(".").first,
+ :labels => labels,
+ :scrape_interval => scrape_interval,
+ :scrape_timeout => scrape_timeout,
:metric_relabel => metric_relabel
}
end
+ Hash(client[:prometheus][:junos]).each do |instance, details|
+ junos_targets << {
+ :instance => instance,
+ :target => details[:address],
+ :address => client[:prometheus][:addresses]["junos"],
+ :labels => Array(details[:labels])
+ }
+ end
+
Hash(client[:prometheus][:snmp]).each do |instance, details|
snmp_targets << {
:instance => instance,
:target => details[:address],
- :module => details[:module],
+ :modules => details[:modules],
:address => client[:prometheus][:addresses]["snmp"],
:labels => Array(details[:labels])
}
register_target false
end
-template "/etc/default/prometheus" do
- source "default.prometheus.erb"
- owner "root"
- group "root"
- mode "644"
+package "prometheus"
+
+systemd_service "prometheus-executable" do
+ service "prometheus"
+ dropin "executable"
+ exec_start "/opt/prometheus-server/prometheus/prometheus --config.file=/etc/prometheus/prometheus.yml --web.enable-admin-api --web.external-url=https://prometheus.openstreetmap.org/prometheus --storage.tsdb.path=/var/lib/prometheus/metrics2 --storage.tsdb.retention.time=540d"
+ timeout_stop_sec 300
+ notifies :restart, "service[prometheus]"
end
template "/etc/prometheus/prometheus.yml" do
owner "root"
group "root"
mode "644"
- variables :jobs => jobs, :snmp_targets => snmp_targets, :certificates => certificates
+ variables :jobs => jobs, :junos_targets => junos_targets, :snmp_targets => snmp_targets, :certificates => certificates
end
template "/etc/prometheus/alert_rules.yml" do
service "prometheus" do
action [:enable, :start]
- subscribes :restart, "template[/etc/default/prometheus]"
subscribes :reload, "template[/etc/prometheus/prometheus.yml]"
subscribes :reload, "template[/etc/prometheus/alert_rules.yml]"
+ subscribes :restart, "archive_file[#{cache_dir}/prometheus.linux.tar.gz]"
end
-template "/etc/default/prometheus-alertmanager" do
- source "default.alertmanager.erb"
- owner "root"
- group "root"
- mode "644"
+systemd_service "prometheus-alertmanager" do
+ description "Prometheus alert manager"
+ type "simple"
+ user "prometheus"
+ exec_start "/opt/prometheus-server/alertmanager/alertmanager --config.file=/etc/prometheus/alertmanager.yml --storage.path=/var/lib/prometheus/alertmanager --web.external-url=https://prometheus.openstreetmap.org/alertmanager"
+ exec_reload "/bin/kill -HUP $MAINPID"
+ timeout_stop_sec 20
+ restart "on-failure"
+ notifies :restart, "service[prometheus-alertmanager]"
+end
+
+link "/usr/local/bin/promtool" do
+ to "/opt/prometheus-server/prometheus/promtool"
end
template "/etc/prometheus/alertmanager.yml" do
mode "644"
end
+directory "/var/lib/prometheus/alertmanager" do
+ owner "prometheus"
+ group "prometheus"
+ mode "755"
+end
+
service "prometheus-alertmanager" do
action [:enable, :start]
- subscribes :restart, "template[/etc/default/prometheus-alertmanager]"
subscribes :reload, "template[/etc/prometheus/alertmanager.yml]"
+ subscribes :restart, "systemd_service[prometheus-alertmanager]"
+ subscribes :restart, "archive_file[#{cache_dir}/alertmanager.linux.tar.gz]"
+end
+
+directory "/etc/amtool" do
+ owner "root"
+ group "root"
+ mode "755"
end
-template "/etc/prometheus/amtool.yml" do
+template "/etc/amtool/config.yml" do
source "amtool.yml.erb"
owner "root"
group "root"
mode "644"
end
+link "/usr/local/bin/amtool" do
+ to "/opt/prometheus-server/alertmanager/amtool"
+end
+
+template "/etc/prometheus/karma.yml" do
+ source "karma.yml.erb"
+ owner "root"
+ group "root"
+ mode "644"
+end
+
+systemd_service "prometheus-karma" do
+ description "Alert dashboard for Prometheus Alertmanager"
+ user "prometheus"
+ exec_start "/opt/prometheus-server/karma/karma-linux-#{prometheus_arch} --config.file=/etc/prometheus/karma.yml"
+ sandbox :enable_network => true
+ restart "on-failure"
+end
+
+service "prometheus-karma" do
+ action [:enable, :start]
+ subscribes :restart, "template[/etc/prometheus/karma.yml]"
+ subscribes :restart, "archive_file[#{cache_dir}/karma-linux.tar.gz]"
+ subscribes :restart, "systemd_service[prometheus-karma]"
+end
+
package "grafana-enterprise"
template "/etc/grafana/grafana.ini" do
apache_module "alias"
apache_module "proxy_http"
+apache_module "proxy_wstunnel"
ssl_certificate "prometheus.openstreetmap.org" do
- domains ["prometheus.openstreetmap.org", "prometheus.osm.org"]
+ domains ["prometheus.openstreetmap.org", "prometheus.osm.org", "munin.openstreetmap.org", "munin.osm.org"]
notifies :reload, "service[apache2]"
end
apache_site "prometheus.openstreetmap.org" do
template "apache.erb"
+ variables :admin_hosts => admins["hosts"]
end
template "/etc/cron.daily/prometheus-backup" do
group "root"
mode "750"
end
+
+package %w[
+ curl
+ jq
+]
+
+directory "/var/lib/prometheus/.aws" do
+ user "prometheus"
+ group "prometheus"
+ mode "755"
+end
+
+template "/var/lib/prometheus/.aws/credentials" do
+ source "aws-credentials.erb"
+ user "prometheus"
+ group "prometheus"
+ mode "600"
+ variables :passwords => passwords
+end
+
+template "/usr/local/bin/prometheus-backup-data" do
+ source "backup-data.erb"
+ owner "root"
+ group "root"
+ mode "755"
+end
+
+systemd_service "prometheus-backup-data" do
+ description "Backup prometheus data to S3"
+ user "prometheus"
+ exec_start "/usr/local/bin/prometheus-backup-data"
+ read_write_paths %w[
+ /var/lib/prometheus/.aws
+ /var/lib/prometheus/metrics2/snapshots
+ ]
+ sandbox :enable_network => true
+end
+
+systemd_timer "prometheus-backup-data" do
+ description "Backup prometheus data to S3"
+ on_calendar "03:11"
+end
+
+service "prometheus-backup-data.timer" do
+ action [:enable, :start]
+end
--- /dev/null
+#
+# Cookbook:: prometheus
+# Recipe:: smokeping
+#
+# Copyright:: 2023, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "prometheus"
+
+ip4_hosts = []
+ip6_hosts = []
+
+search(:node, "networking:interfaces") do |host|
+ next if host.name == node.name
+
+ ip4_hosts << host[:fqdn] unless host.ipaddresses(:role => :external, :family => :inet).empty?
+ ip6_hosts << host[:fqdn] unless host.ipaddresses(:role => :external, :family => :inet6).empty?
+end
+
+template "/etc/prometheus/exporters/smokeping.yml" do
+ source "smokeping.yml.erb"
+ owner "root"
+ group "root"
+ mode "644"
+ variables :ip4_hosts => ip4_hosts, :ip6_hosts => ip6_hosts
+end
+
+prometheus_exporter "smokeping" do
+ port 9374
+ options "--config.file=/etc/prometheus/exporters/smokeping.yml"
+ capability_bounding_set "CAP_NET_RAW"
+ ambient_capabilities "CAP_NET_RAW"
+ private_users false
+ subscribes :restart, "template[/etc/prometheus/exporters/smokeping.yml]"
+end
property :collector, :kind_of => String, :name_property => true
property :interval, :kind_of => [Integer, String], :required => [:create]
+property :user, :kind_of => String
+property :path, :kind_of => String
property :options, :kind_of => [String, Array]
property :environment, :kind_of => Hash, :default => {}
+property :proc_subset, String
+property :capability_bounding_set, [String, Array]
+property :private_devices, [true, false]
+property :private_users, [true, false]
+property :protect_clock, [true, false]
+property :protect_kernel_modules, [true, false]
action :create do
systemd_service service_name do
description "Prometheus #{new_resource.collector} collector"
- user "root"
+ type "oneshot"
+ user new_resource.user
+ dynamic_user new_resource.user.nil?
+ group "adm"
environment new_resource.environment
standard_output "file:/var/lib/prometheus/node-exporter/#{new_resource.collector}.new"
standard_error "journal"
exec_start "#{executable_path} #{executable_options}"
exec_start_post "/bin/mv /var/lib/prometheus/node-exporter/#{new_resource.collector}.new /var/lib/prometheus/node-exporter/#{new_resource.collector}.prom"
- private_tmp true
- protect_system "strict"
- protect_home true
- read_write_paths "/var/lib/prometheus/node-exporter"
- no_new_privileges true
+ sandbox true
+ proc_subset new_resource.proc_subset if new_resource.property_is_set?(:proc_subset)
+ capability_bounding_set new_resource.capability_bounding_set if new_resource.property_is_set?(:capability_bounding_set)
+ private_devices new_resource.private_devices if new_resource.property_is_set?(:private_devices)
+ private_users new_resource.private_users if new_resource.property_is_set?(:private_users)
+ protect_clock new_resource.protect_clock if new_resource.property_is_set?(:protect_clock)
+ protect_kernel_modules new_resource.protect_kernel_modules if new_resource.property_is_set?(:protect_kernel_modules)
+ read_write_paths ["/var/lib/prometheus/node-exporter", "/var/lock", "/var/log"]
end
systemd_timer service_name do
end
def executable_path
- "/opt/prometheus/collectors/#{new_resource.collector}/#{new_resource.collector}_collector"
+ new_resource.path || "/opt/prometheus-exporters/collectors/#{new_resource.collector}/#{new_resource.collector}_collector"
end
def executable_options
property :port, :kind_of => Integer, :required => [:create]
property :listen_switch, :kind_of => String, :default => "web.listen-address"
property :listen_type, :kind_of => String, :default => "address"
-property :user, :kind_of => String, :default => "root"
+property :user, :kind_of => String
+property :group, :kind_of => String
property :command, :kind_of => String
property :options, :kind_of => [String, Array]
property :environment, :kind_of => Hash, :default => {}
+property :protect_proc, String
+property :proc_subset, String
+property :capability_bounding_set, [String, Array]
+property :ambient_capabilities, [String, Array]
+property :private_devices, [true, false]
+property :private_users, [true, false]
+property :protect_clock, [true, false]
+property :restrict_address_families, [String, Array]
+property :remove_ipc, [true, false]
+property :system_call_filter, [String, Array]
property :service, :kind_of => String
+property :labels, :kind_of => Hash, :default => {}
+property :scrape_interval, :kind_of => String
+property :scrape_timeout, :kind_of => String
property :metric_relabel, :kind_of => Array
property :register_target, :kind_of => [TrueClass, FalseClass], :default => true
+property :ssh, [true, false]
action :create do
+ if new_resource.ssh && new_resource.user.nil?
+ keys = data_bag_item("prometheus", "keys")
+
+ directory "/var/lib/private/prometheus/#{new_resource.exporter}-exporter" do
+ mode "700"
+ recursive true
+ end
+
+ file "/var/lib/private/prometheus/#{new_resource.exporter}-exporter/id_rsa" do
+ content keys["ssh"].join("\n")
+ mode "400"
+ end
+
+ cookbook_file "/var/lib/private/prometheus/#{new_resource.exporter}-exporter/id_rsa.pub" do
+ mode "644"
+ end
+ end
+
systemd_service service_name do
+ after "network-online.target"
+ wants "network-online.target"
description "Prometheus #{new_resource.exporter} exporter"
type "simple"
user new_resource.user
+ dynamic_user new_resource.user.nil?
+ group new_resource.group
environment new_resource.environment
exec_start "#{executable_path} #{new_resource.command} #{executable_options}"
- private_tmp true
- protect_system "strict"
- protect_home true
- no_new_privileges true
+ sandbox :enable_network => true
+ state_directory "prometheus/#{new_resource.exporter}-exporter" if new_resource.ssh && new_resource.user.nil?
+ protect_proc new_resource.protect_proc if new_resource.property_is_set?(:protect_proc)
+ proc_subset new_resource.proc_subset if new_resource.property_is_set?(:proc_subset)
+ capability_bounding_set new_resource.capability_bounding_set if new_resource.property_is_set?(:capability_bounding_set)
+ ambient_capabilities new_resource.ambient_capabilities if new_resource.property_is_set?(:ambient_capabilities)
+ private_devices new_resource.private_devices if new_resource.property_is_set?(:private_devices)
+ private_users new_resource.private_users if new_resource.property_is_set?(:private_users)
+ protect_clock new_resource.protect_clock if new_resource.property_is_set?(:protect_clock)
+ restrict_address_families new_resource.restrict_address_families if new_resource.property_is_set?(:restrict_address_families)
+ remove_ipc new_resource.remove_ipc if new_resource.property_is_set?(:remove_ipc)
+ system_call_filter new_resource.system_call_filter if new_resource.property_is_set?(:system_call_filter)
end
service service_name do
firewall_rule "accept-prometheus-#{new_resource.exporter}" do
action :accept
- source "osm"
- dest "fw"
- proto "tcp:syn"
+ context :incoming
+ protocol :tcp
+ source :osm
dest_ports new_resource.port
only_if { node[:prometheus][:mode] == "external" }
end
node.default[:prometheus][:exporters][new_resource.port] = {
:name => new_resource.exporter,
:address => listen_address,
+ :labels => new_resource.labels,
+ :scrape_interval => new_resource.scrape_interval,
+ :scrape_timeout => new_resource.scrape_timeout,
:metric_relabel => new_resource.metric_relabel
}
end
action :restart do
service service_name do
action :restart
+ only_if { service_exists? }
end
end
end
end
+ def service_exists?
+ ::File.exist?("/etc/systemd/system/#{service_name}.service")
+ end
+
def executable_path
- "/opt/prometheus/exporters/#{new_resource.exporter}/#{new_resource.exporter}_exporter"
+ if ::File.exist?("#{executable_directory}/#{executable_name}_#{executable_architecture}")
+ "#{executable_directory}/#{executable_name}_#{executable_architecture}"
+ else
+ "#{executable_directory}/#{executable_name}"
+ end
+ end
+
+ def executable_directory
+ "/opt/prometheus-exporters/exporters/#{new_resource.exporter}"
+ end
+
+ def executable_name
+ "#{new_resource.exporter}_exporter"
+ end
+
+ def executable_architecture
+ node[:kernel][:machine]
end
def executable_options
end
def after_created
- subscribes :restart, "git[/opt/prometheus]"
+ subscribes :restart, "git[/opt/prometheus-exporters]"
end
# DO NOT EDIT - This file is being maintained by Chef
groups:
- - name: alertmanager
+ - name: amsterdam
rules:
- - alert: prometheus target missing
- expr: up == 0
- for: 5m
+ - alert: uplink
+ expr: junos_interface_up{site="amsterdam",name=~"ge-[01]/2/2"} != 1
+ for: 6m
labels:
- alertgroup: "prometheus"
+ alertgroup: "amsterdam"
+ annotations:
+ status: "{{ $value }}"
+ - alert: pdu current draw
+ expr: rPDU2PhaseStatusCurrent{site="amsterdam",rPDU2PhaseStatusIndex="1"} / 10 > 28
+ for: 6m
+ labels:
+ alertgroup: "amsterdam"
+ annotations:
+ current: "{{ $value | humanize }}A"
+ - alert: site power
+ expr: sum(avg_over_time(rPDU2PhaseStatusApparentPower{site="amsterdam",rPDU2PhaseStatusIndex="1"}[1h]) / 100) > 3.5
+ for: 6m
+ labels:
+ alertgroup: "amsterdam"
+ annotations:
+ current: "{{ $value | humanize }}kVA"
+ - alert: site temperature
+ expr: min(rPDU2SensorTempHumidityStatusTempC{site="amsterdam"}) / 10 < 18 or min(rPDU2SensorTempHumidityStatusTempC{site="amsterdam"}) / 10 > 26
+ for: 6m
+ labels:
+ alertgroup: "amsterdam"
+ annotations:
+ temperature: "{{ $value | humanize }}C"
+ - alert: site humidity
+ expr: max(rPDU2SensorTempHumidityStatusRelativeHumidity{site="amsterdam"}) / 100 < 0.25 or max(rPDU2SensorTempHumidityStatusRelativeHumidity{site="amsterdam"}) / 100 > 0.65
+ for: 6m
+ labels:
+ alertgroup: "amsterdam"
+ annotations:
+ humidity: "{{ $value | humanizePercentage }}"
- name: apache
rules:
- alert: apache down
alertgroup: "{{ $labels.instance }}"
annotations:
busy_workers: "{{ $value | humanizePercentage }}"
+ - alert: apache connection limit
+ expr: (apache_connections{state="total"} - on (instance) apache_connections{state="closing"}) / on (instance) (apache_server_limit * on (instance) (apache_threads_per_child + on (instance) (apache_async_request_worker_factor * on (instance) apache_workers{state="idle"} / on(instance) apache_processes{state="all"}))) > 0.8
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ annotations:
+ connections: "{{ $value | humanizePercentage }}"
+ - name: chef
+ rules:
+ - alert: chef client not running
+ expr: time() - node_systemd_timer_last_trigger_seconds{name="chef-client.timer"} > 3600
+ for: 12h
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ annotations:
+ down_time: "{{ $value | humanizeDuration }}"
+ - name: cisco
+ rules:
+ - alert: cisco fan alarm
+ expr: rlPhdUnitEnvParamFan1Status{rlPhdUnitEnvParamFan1Status!="normal"} > 0 or rlPhdUnitEnvParamFan2Status{rlPhdUnitEnvParamFan2Status!="normal"} > 0
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.site }}"
+ annotations:
+ fan_rpm: "{{ with printf \"rlPhdUnitEnvParamFan1Speed{site='%s',instance='%s',rlPhdUnitEnvParamStackUnit='%s'}\" $labels.site $labels.instance $labels.rlPhdUnitEnvParamStackUnit | query }}{{ . | first | value | humanize }}rpm{{end}}"
+ - alert: cisco temperature alarm
+ expr: rlPhdUnitEnvParamTempSensorStatus{rlPhdUnitEnvParamTempSensorStatus!="ok"} > 0
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.site }}"
+ annotations:
+ temp_celsius: "{{ with printf \"rlPhdUnitEnvParamTempSensorValue{site='%s',instance='%s',rlPhdUnitEnvParamStackUnit='%s'}\" $labels.site $labels.instance $labels.rlPhdUnitEnvParamStackUnit | query }}{{ . | first | value | humanize }}C{{end}}"
+ - alert: cisco main power alarm
+ expr: rlPhdUnitEnvParamMainPSStatus{rlPhdUnitEnvParamMainPSStatus!="normal"} > 0
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.site }}"
+ - alert: cisco redundant power alarm
+ expr: rlPhdUnitEnvParamRedundantPSStatus{rlPhdUnitEnvParamRedundantPSStatus!="normal"} > 0
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.site }}"
+ - name: cpu
+ rules:
+ - alert: cpu pressure
+ expr: rate(node_pressure_cpu_waiting_seconds_total[5m]) > 0.75
+ for: 60m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ annotations:
+ pressure: "{{ $value | humanizePercentage }}"
- name: database
rules:
- - alert: postgres replication delay
- expr: pg_replication_lag_seconds > 5
+ - alert: active rails queries
+ expr: sum(pg_stat_activity_count{datname="openstreetmap",usename="rails",state="active"}) by (instance) > 50 and on (instance) chef_role{name="db-master"}
for: 5m
labels:
alertgroup: database
annotations:
- delay: "{{ $value | humanizeDuration }}"
+ queries: "{{ $value }}"
+ - alert: active cgimap queries
+ expr: sum(pg_stat_activity_count{datname="openstreetmap",usename="cgimap",state="active"}) by (instance) > 30 and on (instance) chef_role{name="db-master"}
+ for: 5m
+ labels:
+ alertgroup: database
+ annotations:
+ delay: "{{ $value }}"
+ - name: discourse
+ rules:
+ - alert: discourse job failure rate
+ expr: rate(discourse_job_failures[5m]) > 0
+ for: 5m
+ labels:
+ alertgroup: discourse
+ annotations:
+ failure_rate: "{{ $value }} jobs/s"
+ - name: dublin
+ rules:
+ - alert: uplink
+ expr: junos_interface_up{site="dublin",name=~"ge-[01]/2/2"} != 1
+ for: 6m
+ labels:
+ alertgroup: "dublin"
+ annotations:
+ status: "{{ $value }}"
+ - alert: pdu current draw
+ expr: rPDU2PhaseStatusCurrent{site="dublin",rPDU2PhaseStatusIndex="1"} / 10 > 28
+ for: 6m
+ labels:
+ alertgroup: "dublin"
+ annotations:
+ current: "{{ $value | humanize }}A"
+ - alert: site power
+ expr: sum(avg_over_time(rPDU2PhaseStatusApparentPower{site="dublin",rPDU2PhaseStatusIndex="1"}[1h]) / 100) > 4
+ for: 6m
+ labels:
+ alertgroup: "dublin"
+ annotations:
+ current: "{{ $value | humanize }}kVA"
+ - alert: site temperature
+ expr: min(rPDU2SensorTempHumidityStatusTempC{site="dublin"}) / 10 < 18 or min(rPDU2SensorTempHumidityStatusTempC{site="dublin"}) / 10 > 26
+ for: 6m
+ labels:
+ alertgroup: "dublin"
+ annotations:
+ temperature: "{{ $value | humanize }}C"
+ - alert: site humidity
+ expr: max(rPDU2SensorTempHumidityStatusRelativeHumidity{site="dublin"}) / 100 < 0.25 or max(rPDU2SensorTempHumidityStatusRelativeHumidity{site="dublin"}) / 100 > 0.65
+ for: 6m
+ labels:
+ alertgroup: "dublin"
+ annotations:
+ humidity: "{{ $value | humanizePercentage }}"
+ - name: fastly
+ rules:
+ - alert: fastly error rate
+ expr: sum(rate(fastly_rt_status_group_total{status_group="5xx"}[5m])) by (service_name, datacenter) / sum(rate(fastly_rt_status_group_total[5m])) by (service_name, datacenter) > 0.005
+ for: 15m
+ labels:
+ alertgroup: fastly
+ annotations:
+ error_rate: "{{ $value | humanizePercentage }}"
+ - alert: fastly frontend healthcheck warning
+ expr: count(fastly_healthcheck_status == 0) by (service, datacenter) > 2
+ for: 15m
+ labels:
+ alertgroup: fastly
+ - alert: fastly frontend healthcheck critical
+ expr: count(fastly_healthcheck_status == 0) by (service, datacenter) == count(fastly_healthcheck_status) by (service, datacenter)
+ for: 5m
+ labels:
+ alertgroup: fastly
+ - alert: fastly backend healthcheck warning
+ expr: count(fastly_healthcheck_status == 0) by (service, backend) > 10
+ for: 15m
+ labels:
+ alertgroup: fastly
+ - alert: fastly backend healthcheck critical
+ expr: count(fastly_healthcheck_status == 0) by (service, backend) == count(fastly_healthcheck_status) by (service, backend)
+ for: 5m
+ labels:
+ alertgroup: fastly
+ - name: filesystem
+ rules:
+ - alert: readonly filesystem
+ expr: node_filesystem_readonly > min_over_time(node_filesystem_readonly[7d])
+ for: 0m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ - alert: filesystem low on space
+ expr: node_filesystem_avail_bytes / node_filesystem_size_bytes < 0.05
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ annotations:
+ percentage_free: "{{ $value | humanizePercentage }}"
+ free_bytes: "{{ with printf \"node_filesystem_avail_bytes{instance='%s',mountpoint='%s'}\" $labels.instance $labels.mountpoint | query }}{{ . | first | value | humanize1024 }}bytes{{end}}"
+ total_total: "{{ with printf \"node_filesystem_size_bytes{instance='%s',mountpoint='%s'}\" $labels.instance $labels.mountpoint | query }}{{ . | first | value | humanize1024 }}bytes{{end}}"
+ - alert: filesystem low on inodes
+ expr: node_filesystem_files_free / node_filesystem_files < 0.1
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ annotations:
+ percentage_free: "{{ $value | humanizePercentage }}"
+ free_inodes: "{{ with printf \"node_filesystem_files_free{instance='%s',mountpoint='%s'}\" $labels.instance $labels.mountpoint | query }}{{ . | first | value }}{{end}}"
+ total_inodes: "{{ with printf \"node_filesystem_files{instance='%s',mountpoint='%s'}\" $labels.instance $labels.mountpoint | query }}{{ . | first | value }}{{end}}"
- name: hwmon
rules:
- alert: hwmon fan alarm
in_volts: "{{ with printf \"node_hwmon_in_volts{instance='%s',chip='%s',sensor='%s'}\" $labels.instance $labels.chip $labels.sensor | query }}{{ . | first | value | humanize }}V{{end}}"
in_min_volts: "{{ with printf \"node_hwmon_in_min_volts{instance='%s',chip='%s',sensor='%s'}\" $labels.instance $labels.chip $labels.sensor | query }}{{ . | first | value | humanize }}V{{end}}"
in_max_volts: "{{ with printf \"node_hwmon_in_max_volts{instance='%s',chip='%s',sensor='%s'}\" $labels.instance $labels.chip $labels.sensor | query }}{{ . | first | value | humanize }}V{{end}}"
+ - name: io
+ rules:
+ - alert: io pressure
+ expr: rate(node_pressure_io_waiting_seconds_total[5m]) > 0.6
+ for: 60m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ annotations:
+ pressure: "{{ $value | humanizePercentage }}"
- name: ipmi
rules:
- alert: ipmi fan alarm
for: 5m
labels:
alertgroup: "{{ $labels.instance }}"
+ - name: juniper
+ rules:
+ - alert: juniper red alarms
+ expr: juniper_alarms_red_count > 0
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.site }}"
+ annotations:
+ alarm_count: "{{ $value }} alarms"
+ - alert: juniper yellow alarms
+ expr: juniper_alarms_yellow_count > 0
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.site }}"
+ annotations:
+ alarm_count: "{{ $value }} alarms"
+ - alert: juniper cpu alarm
+ expr: junos_route_engine_load_average_five / 2 > 0.5
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.site }}"
+ annotations:
+ load_average: "{{ $value | humanizePercentage }}"
+ - alert: juniper fan alarm
+ expr: junos_environment_fan_up != 1
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.site }}"
+ - alert: juniper power alarm
+ expr: junos_environment_power_up != 1
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.site }}"
+ - alert: juniper laser receive power
+ expr: junos_interface_diagnostics_laser_rx_dbm < -12 and on (site, instance, name) junos_interface_admin_up == 1
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.site }}"
+ annotations:
+ power: "{{ $value }} dBm"
+ - alert: juniper laser transmit power
+ expr: junos_interface_diagnostics_laser_output_dbm < -8 and on (site, instance, name) junos_interface_admin_up == 1
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.site }}"
+ annotations:
+ power: "{{ $value }} dBm"
+ - name: mail
+ rules:
+ - alert: exim down
+ expr: exim_up == 0
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ - alert: exim queue length
+ expr: exim_queue > ignoring(job) exim_queue_limit
+ for: 60m
+ labels:
+ alertgroup: mail
+ annotations:
+ queue_length: "{{ $value }}"
+ - alert: mailman queue length
+ expr: mailman_queue_length > 200
+ for: 60m
+ labels:
+ alertgroup: mail
+ annotations:
+ queue_length: "{{ $value }}"
- name: mdadm
rules:
- alert: mdadm array inactive
active: "{{ with printf \"node_md_disks{instance='%s',device='%s',state='active'}\" $labels.instance $labels.device | query }}{{ . | first | value | humanize }} disks{{end}}"
failed: "{{ with printf \"node_md_disks{instance='%s',device='%s',state='failed'}\" $labels.instance $labels.device | query }}{{ . | first | value | humanize }} disks{{end}}"
spare: "{{ with printf \"node_md_disks{instance='%s',device='%s',state='spare'}\" $labels.instance $labels.device | query }}{{ . | first | value | humanize }} disks{{end}}"
+ - alert: mdadm array degraded
+ expr: sum (node_md_disks{state="active"}) without (state) < node_md_disks_required
+ for: 0m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ annotations:
+ required: "{{ with printf \"node_md_disks_required{instance='%s',device='%s'}\" $labels.instance $labels.device | query }}{{ . | first | value | humanize }} disks{{end}}"
+ active: "{{ with printf \"node_md_disks{instance='%s',device='%s',state='active'}\" $labels.instance $labels.device | query }}{{ . | first | value | humanize }} disks{{end}}"
+ failed: "{{ with printf \"node_md_disks{instance='%s',device='%s',state='failed'}\" $labels.instance $labels.device | query }}{{ . | first | value | humanize }} disks{{end}}"
+ spare: "{{ with printf \"node_md_disks{instance='%s',device='%s',state='spare'}\" $labels.instance $labels.device | query }}{{ . | first | value | humanize }} disks{{end}}"
- alert: mdadm disk failed
expr: node_md_disks{state="failed"} > 0
for: 0m
rules:
- alert: low memory
expr: node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes < 0.1
- for: 5m
+ for: 15m
labels:
alertgroup: "{{ $labels.instance }}"
annotations:
memory_free: "{{ $value | humanizePercentage }}"
- alert: memory pressure
- expr: rate(node_vmstat_pgmajfault[1m]) > 1000
- for: 5m
+ expr: rate(node_pressure_memory_waiting_seconds_total[5m]) > 0.6
+ for: 60m
labels:
alertgroup: "{{ $labels.instance }}"
annotations:
- major_page_faults: "{{ $value }} faults/s"
+ pressure: "{{ $value | humanizePercentage }}"
- alert: oom kill detected
expr: increase(node_vmstat_oom_kill[1m]) > 0
for: 0m
alertgroup: "{{ $labels.instance }}"
annotations:
new_oom_kills: "{{ $value }}"
+ - name: mysql
+ rules:
+ - alert: mysql down
+ expr: mysql_up == 0
+ for: 1m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ - alert: mysql connection limit
+ expr: mysql_global_status_max_used_connections / mysql_global_variables_max_connections > 0.8
+ for: 1m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ annotations:
+ connections_used: "{{ $value | humanizePercentage }}"
+ - alert: mysql connection errors
+ expr: increase(mysql_global_status_connection_errors_total[1m]) > 0
+ for: 0m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ annotations:
+ error_count: "{{ $value }}"
- name: network
rules:
+ - alert: interface redundancy lost
+ expr: node_bonding_active < 2 and on (instance, master) label_replace(chef_network_interface{bond_mode="802.3ad"}, "master", "$1", "name", "(.*)")
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ annotations:
+ link_count: "{{ $value }}"
- alert: interface transmit rate
- expr: rate(node_network_transmit_bytes_total[1m]) / node_network_speed_bytes > 0.98
+ expr: rate(node_network_transmit_bytes_total[1m]) / node_network_speed_bytes > 0.99
for: 5m
labels:
alertgroup: "{{ $labels.instance }}"
annotations:
bandwidth_used: "{{ $value | humanizePercentage }}"
- alert: interface receive rate
- expr: rate(node_network_receive_bytes_total[1m]) / node_network_speed_bytes > 0.98
+ expr: rate(node_network_receive_bytes_total[1m]) / node_network_speed_bytes > 0.99
for: 5m
labels:
alertgroup: "{{ $labels.instance }}"
annotations:
bandwidth_used: "{{ $value | humanizePercentage }}"
- alert: interface transmit errors
- expr: rate(node_network_transmit_errs_total[1m]) / rate(node_network_transmit_packets_total[1m]) > 0.01
+ expr: rate(node_network_transmit_errs_total{device!~"wg.*"}[1m]) / rate(node_network_transmit_packets_total{device!~"wg.*"}[1m]) > 0.01
for: 5m
labels:
alertgroup: "{{ $labels.instance }}"
annotations:
error_rate: "{{ $value | humanizePercentage }}"
+ - alert: wireguard interface transmit errors
+ expr: rate(node_network_transmit_errs_total{device=~"wg.*"}[1m]) / rate(node_network_transmit_packets_total{device=~"wg.*"}[1m]) > 0.05
+ for: 1h
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ annotations:
+ error_rate: "{{ $value | humanizePercentage }}"
- alert: interface receive errors
expr: rate(node_network_receive_errs_total[1m]) / rate(node_network_receive_packets_total[1m]) > 0.01
for: 5m
alertgroup: "{{ $labels.instance }}"
annotations:
entries_used: "{{ $value | humanizePercentage }}"
+ - name: nominatim
+ rules:
+ - alert: nominatim replication delay
+ expr: nominatim_replication_delay > 10800
+ for: 1h
+ labels:
+ alertgroup: nominatim
+ annotations:
+ delay: "{{ $value | humanizeDuration }}"
+ - name: overpass
+ rules:
+ - alert: overpass osm database age
+ expr: overpass_database_age_seconds{database="osm"} > 3600
+ for: 1h
+ labels:
+ alertgroup: overpass
+ annotations:
+ age: "{{ $value | humanizeDuration }}"
+ - alert: overpass area database age
+ expr: overpass_database_age_seconds{database="area"} > 86400
+ for: 1h
+ labels:
+ alertgroup: overpass
+ annotations:
+ age: "{{ $value | humanizeDuration }}"
+ - name: passenger
+ rules:
+ - alert: passenger down
+ expr: passenger_up == 0
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ - alert: passenger queuing
+ expr: passenger_top_level_request_queue > 0
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ - alert: passenger application queuing
+ expr: passenger_app_request_queue > 0
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ - name: planet
+ rules:
+ - alert: planet dump overdue
+ expr: time() - file_stat_modif_time_seconds{path=~"/store/planet/(pbf|planet)/.*"} > 7 * 86400 and ignoring (job, name, path) chef_role{name="planetdump"} == 1
+ for: 24h
+ labels:
+ alertgroup: planet
+ annotations:
+ overdue_by: "{{ $value | humanizeDuration }}"
+ - alert: notes dump overdue
+ expr: time() - file_stat_modif_time_seconds{path=~"/store/planet/notes/.*"} > 86400 and ignoring (job, name, path) chef_role{name="planetdump"} == 1
+ for: 6h
+ labels:
+ alertgroup: planet
+ annotations:
+ overdue_by: "{{ $value | humanizeDuration }}"
+ - alert: daily replication feed delayed
+ expr: time() - file_stat_modif_time_seconds{path=~"/store/planet/replication/day/.*"} > 86400 and ignoring (job, name, path) chef_role{name="planetdump"} == 1
+ for: 3h
+ labels:
+ alertgroup: planet
+ annotations:
+ delayed_by: "{{ $value | humanizeDuration }}"
+ - alert: hourly replication feed delayed
+ expr: time() - file_stat_modif_time_seconds{path=~"/store/planet/replication/hour/.*"} > 3600 and ignoring (job, name, path) chef_role{name="planetdump"} == 1
+ for: 30m
+ labels:
+ alertgroup: planet
+ annotations:
+ delayed_by: "{{ $value | humanizeDuration }}"
+ - alert: minutely replication feed delayed
+ expr: time() - file_stat_modif_time_seconds{path=~"/store/planet/replication/minute/.*"} > 60 and ignoring (job, name, path) chef_role{name="planetdump"} == 1
+ for: 5m
+ labels:
+ alertgroup: planet
+ annotations:
+ delayed_by: "{{ $value | humanizeDuration }}"
+ - alert: changeset replication feed delayed
+ expr: time() - file_stat_modif_time_seconds{path=~"/store/planet/replication/changesets/.*"} > 60 and ignoring (job, name, path) chef_role{name="planetdump"} == 1
+ for: 5m
+ labels:
+ alertgroup: planet
+ annotations:
+ delayed_by: "{{ $value | humanizeDuration }}"
- name: postgresql
rules:
- alert: postgresql down
labels:
alertgroup: "{{ $labels.instance }}"
- alert: postgresql replication delay
- expr: pg_replication_lag_seconds > 5
- for: 1m
+ expr: pg_replication_lag_seconds > 30
+ for: 15m
labels:
alertgroup: "{{ $labels.instance }}"
annotations:
annotations:
connections_used: "{{ $value | humanizePercentage }}"
- alert: postgresql deadlocks
- expr: increase(pg_stat_database_deadlocks[1m]) > 5
+ expr: increase(pg_stat_database_deadlocks{datname!="nominatim"}[1m]) > 5
for: 0m
labels:
alertgroup: "{{ $labels.instance }}"
annotations:
new_deadlocks: "{{ $value }}"
- - alert: postgresql slow queries
- expr: pg_slow_queries > 0
+ - alert: postgresql idle transactions
+ expr: sum(pg_process_idle_seconds_count{state="idle in transaction"}) by (instance, server) > sum(pg_process_idle_seconds_bucket{state="idle in transaction",le="300"}) by (instance, server)
for: 5m
labels:
alertgroup: "{{ $labels.instance }}"
annotations:
queries: "{{ $value }}"
+ - name: prometheus
+ rules:
+ - alert: prometheus configuration error
+ expr: prometheus_config_last_reload_successful == 0
+ for: 10m
+ labels:
+ alertgroup: "prometheus"
+ - alert: prometheus target missing
+ expr: up == 0
+ for: 10m
+ labels:
+ alertgroup: "prometheus"
+ - alert: node exporter text file scrape error
+ expr: node_textfile_scrape_error > 0
+ for: 10m
+ labels:
+ alertgroup: "prometheus"
+ - name: raid
+ rules:
+ - alert: raid controller battery failed
+ expr: ohai_controller_info{battery_status="failed"} > 0
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ - alert: raid controller battery recharging
+ expr: ohai_controller_info{battery_status="recharging"} > 0
+ for: 4h
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ - alert: raid array degraded
+ expr: ohai_array_info{status="degraded"} > 0
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ - alert: raid disk failed
+ expr: ohai_disk_info{status="failed"} > 0
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ - name: rasdaemon
+ rules:
+ - alert: memory controller errors
+ expr: increase(rasdaemon_mc_events_total[1m]) > 0
+ for: 0m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ annotations:
+ new_errors: "{{ $value }}"
+ - alert: pcie aer errors
+ expr: increase(rasdaemon_aer_events_total[1m]) > 0
+ for: 0m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ annotations:
+ new_errors: "{{ $value }}"
+ - name: smart
+ rules:
+ - alert: smart failure
+ expr: smart_health_status == 0
+ for: 60m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ - alert: smart ssd wearout approaching
+ expr: smart_percentage_used / 100 >= 0.8
+ for: 60m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ annotations:
+ percentage_used: "{{ $value | humanizePercentage }}"
+ - name: smokeping
+ rules:
+ - alert: packet loss
+ expr: 1 - (rate(smokeping_response_duration_seconds_count[5m]) / rate(smokeping_requests_total[5m])) > 0.02
+ for: 10m
+ labels:
+ alertgroup: smokeping
+ annotations:
+ loss_rate: "{{ $value | humanizePercentage }}"
+ - name: snmp
+ rules:
+ - alert: snmp pdus missing
+ expr: max_over_time(snmp_scrape_pdus_returned[1d]) - snmp_scrape_pdus_returned > 0
+ for: 15m
+ labels:
+ alertgroup: snmp
+ annotations:
+ missing_pdus: "{{ $value }}"
- name: ssl
rules:
- alert: ssl certificate probe failed
for: 0m
labels:
alertgroup: ssl
+ - name: statuscake
+ rules:
+ - alert: statuscake uptime check failing
+ expr: statuscake_paused == 0 and statuscake_up == 0
+ for: 10m
+ labels:
+ alertgroup: statuscake
+ - name: systemd
+ rules:
+ - alert: systemd failed service
+ expr: node_systemd_unit_state{state="failed",name!="chef-client.service"} == 1
+ for: 5m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ - alert: systemd failed chef client service
+ expr: sum_over_time(node_systemd_unit_state{state="inactive",name="chef-client.service"}[6h]) == 0
+ for: 0m
+ labels:
+ alertgroup: "{{ $labels.instance }}"
+ - name: taginfo
+ rules:
+ - alert: taginfo planet age
+ expr: time() - taginfo_data_from_seconds > 129600 and on (instance) chef_role{name="taginfo"}
+ for: 0m
+ labels:
+ alertgroup: taginfo
+ annotations:
+ age: "{{ $value | humanizeDuration }}"
+ - alert: taginfo database age
+ expr: time() - taginfo_database_update_finish_seconds > 129600 and on (instance) chef_role{name="taginfo"}
+ for: 0m
+ labels:
+ alertgroup: taginfo
+ annotations:
+ age: "{{ $value | humanizeDuration }}"
+ - alert: taginfo database size
+ expr: abs(delta(taginfo_database_size_bytes[30m])) / taginfo_database_size_bytes > 0.1
+ for: 30m
+ labels:
+ alertgroup: taginfo
+ annotations:
+ size_change: "{{ $value | humanizePercentage }}"
- name: tile
rules:
- alert: renderd replication delay
expr: renderd_replication_delay > 120
- for: 5m
+ for: 15m
labels:
alertgroup: tile
annotations:
alertgroup: tile
annotations:
miss_rate: "{{ $value | humanizePercentage }}"
+ - alert: tile render rate
+ expr: sum(rate(renderd_zoom_metatiles_total[5m])) by (instance) == 0
+ for: 15m
+ labels:
+ alertgroup: tile
+ annotations:
+ render_rate: "{{ $value }} tiles/s"
- name: time
rules:
- alert: clock not synchronising
alertgroup: "{{ $labels.instance }}"
annotations:
skew: "{{ with printf \"node_timex_offset_seconds{instance='%s'}\" $labels.instance | query }} {{ . | humanizeDuration }}{{ end }}"
+ - name: web
+ rules:
+ - alert: web error rate
+ expr: sum(rate(api_call_count_total{status=~"50[0-8]|5[1-9][0-9]"}[5m])) by (instance) / sum(rate(api_call_count_total[5m])) by (instance) > 0.002
+ for: 5m
+ labels:
+ alertgroup: web
+ annotations:
+ error_rate: "{{ $value | humanizePercentage }}"
+ - alert: job processing rate
+ expr: rate(pg_stat_user_tables_n_tup_del{datname="openstreetmap",relname="delayed_jobs"}[1h]) / rate(pg_stat_user_tables_n_tup_ins{datname="openstreetmap",relname="delayed_jobs"}[1h]) < 0.9 and ignoring(job, name, datname, relname, schemaname, server) chef_role{name="db-master"} == 1
+ for: 1h
+ labels:
+ alertgroup: web
+ annotations:
+ job_processing_rate: "{{ $value | humanizePercentage }}"
ServerAlias prometheus.osm.org
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/prometheus.openstreetmap.org-access.log combined
+ CustomLog /var/log/apache2/prometheus.openstreetmap.org-access.log combined_extended
ErrorLog /var/log/apache2/prometheus.openstreetmap.org-error.log
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
ServerName prometheus.openstreetmap.org
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/prometheus.openstreetmap.org-access.log combined
+ CustomLog /var/log/apache2/prometheus.openstreetmap.org-access.log combined_extended
ErrorLog /var/log/apache2/prometheus.openstreetmap.org-error.log
SSLEngine on
SSLCertificateKeyFile /etc/ssl/private/prometheus.openstreetmap.org.key
ProxyPass /prometheus http://localhost:9090/prometheus
- Redirect 403 /alertmanager/api
ProxyPass /alertmanager http://localhost:9093/alertmanager
+ ProxyPass /karma http://localhost:8081/karma
+ ProxyPass /api/live/ws ws://localhost:3000/api/live/ws
ProxyPass / http://localhost:3000/
ProxyPreserveHost on
+
+ <Location /prometheus/api/v1/admin>
+ Require all denied
+ </Location>
+
+ <Location /alertmanager>
+<% @admin_hosts.each do |host| -%>
+ Require ip <%= host %>
+<% end -%>
+ </Location>
+
+ <Location /karma>
+<% @admin_hosts.each do |host| -%>
+ Require ip <%= host %>
+<% end -%>
+ </Location>
+</VirtualHost>
+
+<VirtualHost *:80>
+ ServerName munin.openstreetmap.org
+ ServerAlias munin.osm.org
+ ServerAdmin webmaster@openstreetmap.org
+
+ CustomLog /var/log/apache2/munin.openstreetmap.org-access.log combined_extended
+ ErrorLog /var/log/apache2/munin.openstreetmap.org-error.log
+
+ RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
+ Redirect permanent / https://prometheus.openstreetmap.org/
+</VirtualHost>
+
+<VirtualHost *:443>
+ ServerName munin.openstreetmap.org
+ ServerAlias munin.osm.org
+ ServerAdmin webmaster@openstreetmap.org
+
+ CustomLog /var/log/apache2/munin.openstreetmap.org-access.log combined_extended
+ ErrorLog /var/log/apache2/munin.openstreetmap.org-error.log
+
+ SSLEngine on
+ SSLCertificateFile /etc/ssl/certs/prometheus.openstreetmap.org.pem
+ SSLCertificateKeyFile /etc/ssl/private/prometheus.openstreetmap.org.key
+
+ Redirect permanent / https://prometheus.openstreetmap.org/
</VirtualHost>
--- /dev/null
+[osm-prometheus-data]
+aws_access_key_id = AKIASQUXHPE7KAYP364J
+aws_secret_access_key = <%= @passwords["aws_prometheus_data"] %>
+
+[osm-prometheus-data-upload]
+role_arn=arn:aws:iam::173189593406:role/osm-prometheus-data-upload-role
+source_profile=osm-prometheus-data
--- /dev/null
+#!/bin/sh
+
+# DO NOT EDIT - This file is being maintained by Chef
+
+set -e
+
+SNAPSHOT=$(curl -s -XPOST http://localhost:9090/prometheus/api/v1/admin/tsdb/snapshot | jq -r .data.name)
+
+/opt/awscli/v2/current/bin/aws --profile osm-prometheus-data-upload s3 sync --storage-class=INTELLIGENT_TIERING --no-progress /var/lib/prometheus/metrics2/snapshots/${SNAPSHOT} s3://openstreetmap-prometheus-data
+
+rm -rf /var/lib/prometheus/metrics2/snapshots/${SNAPSHOT}
# HELP chef_network_interface Information about network interfaces
# TYPE chef_network_interface gauge
-<% node.interfaces do |interface| -%>
-chef_network_interface{name="<%= interface[:interface] %>",role="<%= interface[:role].to_s %>",family="<%= interface[:family].to_s %>"} 1
+<% node.interfaces.each do |interface| -%>
+<% if interface[:interface] =~ /^bond\d+$/ -%>
+chef_network_interface{name="<%= interface[:interface] %>",role="<%= interface[:role].to_s %>",bond_mode="<%= interface[:bond][:mode] || 'active-backup' %>"} 1
+<% else -%>
+chef_network_interface{name="<%= interface[:interface] %>",role="<%= interface[:role].to_s %>"} 1
+<% end -%>
<% end -%>
# HELP chef_role Information about chef roles
# TYPE chef_role gauge
<% node[:roles].sort.each do |role| -%>
chef_role{name="<%= role %>"} 1
<% end -%>
-<% if node[:roles].include?("tilecache") -%>
-# HELP chef_tile_parent Information about tile cache parents
-# TYPE chef_tile_parent gauge
-chef_tile_parent{name="<%= node[:tilecache][:tile_parent].split(".").first %>"} 1
+<% node[:prometheus][:metrics].sort.each do |name, details| -%>
+# HELP <%= name %> <%= details[:help] %>
+# TYPE <%= name %> gauge
+<%= name %>{<%= Hash(details[:labels]).map { |k,v| "#{k}=\"#{v}\"" }.join(",") %>} <%= details[:metric] || 1 %>
<% end -%>
--- /dev/null
+apiVersion: v1alpha1
+sts-region: eu-west-1
+discovery:
+ jobs:
+ - type: AWS/S3
+ regions:
+ - eu-west-1
+ - eu-west-2
+ roles:
+ - roleArn: "arn:aws:iam::173189593406:role/osm-cloudwatch-export-role" # osm-main
+ period: 86400
+ length: 86400
+ metrics:
+ - name: BucketSizeBytes
+ statistics: [Average]
+ - name: NumberOfObjects
+ statistics: [Average]
+ - type: AWS/S3
+ regions:
+ - eu-west-1
+ - eu-west-2
+ roles:
+ - roleArn: "arn:aws:iam::173189593406:role/osm-cloudwatch-export-role" # osm-main
+ period: 300
+ length: 300
+ metrics:
+ - name: AllRequests
+ statistics: [Sum]
+ - name: GetRequests
+ statistics: [Sum]
+ - name: PutRequests
+ statistics: [Sum]
+ - name: DeleteRequests
+ statistics: [Sum]
+ - name: HeadRequests
+ statistics: [Sum]
+ - name: PostRequests
+ statistics: [Sum]
+ - name: ListRequests
+ statistics: [Sum]
+ - name: BytesDownloaded
+ statistics: [Sum]
+ - name: BytesUploaded
+ statistics: [Sum]
+ - name: 4xxErrors
+ statistics: [Sum]
+ - name: 5xxErrors
+ statistics: [Sum]
+ - name: FirstByteLatency
+ statistics: [Minimum, Maximum, Average]
+ - name: TotalRequestLatency
+ statistics: [Minimum, Maximum, Average]
+ - name: ReplicationLatency
+ statistics: [Maximum]
+ - name: BytesPendingReplication
+ statistics: [Maximum]
+ - name: OperationsPendingReplication
+ statistics: [Maximum]
+ - name: OperationsFailedReplication
+ statistics: [Sum]
+ - type: AWS/S3
+ regions:
+ - eu-central-1
+ - us-west-2
+ roles:
+ - roleArn: "arn:aws:iam::630658470130:role/osm-cloudwatch-export-role" # osm-planet (pds)
+ period: 86400
+ length: 86400
+ metrics:
+ - name: BucketSizeBytes
+ statistics: [Average]
+ - name: NumberOfObjects
+ statistics: [Average]
+ - type: AWS/S3
+ regions:
+ - eu-central-1
+ - us-west-2
+ roles:
+ - roleArn: "arn:aws:iam::630658470130:role/osm-cloudwatch-export-role" # osm-planet (pds)
+ period: 300
+ length: 300
+ metrics:
+ - name: AllRequests
+ statistics: [Sum]
+ - name: GetRequests
+ statistics: [Sum]
+ - name: PutRequests
+ statistics: [Sum]
+ - name: DeleteRequests
+ statistics: [Sum]
+ - name: HeadRequests
+ statistics: [Sum]
+ - name: PostRequests
+ statistics: [Sum]
+ - name: ListRequests
+ statistics: [Sum]
+ - name: BytesDownloaded
+ statistics: [Sum]
+ - name: BytesUploaded
+ statistics: [Sum]
+ - name: 4xxErrors
+ statistics: [Sum]
+ - name: 5xxErrors
+ statistics: [Sum]
+ - name: FirstByteLatency
+ statistics: [Minimum, Maximum, Average]
+ - name: TotalRequestLatency
+ statistics: [Minimum, Maximum, Average]
+ - name: ReplicationLatency
+ statistics: [Maximum]
+ - name: BytesPendingReplication
+ statistics: [Maximum]
+ - name: OperationsPendingReplication
+ statistics: [Maximum]
+ - name: OperationsFailedReplication
+ statistics: [Sum]
+ - type: AWS/S3
+ regions:
+ - eu-north-1
+ roles:
+ - roleArn: "arn:aws:iam::674083635870:role/osm-cloudwatch-export-role" # osm-backup
+ period: 86400
+ length: 86400
+ metrics:
+ - name: BucketSizeBytes
+ statistics: [Average]
+ - name: NumberOfObjects
+ statistics: [Average]
+ - type: AWS/S3
+ regions:
+ - eu-north-1
+ roles:
+ - roleArn: "arn:aws:iam::674083635870:role/osm-cloudwatch-export-role" # osm-backup
+ period: 300
+ length: 300
+ metrics:
+ - name: AllRequests
+ statistics: [Sum]
+ - name: GetRequests
+ statistics: [Sum]
+ - name: PutRequests
+ statistics: [Sum]
+ - name: DeleteRequests
+ statistics: [Sum]
+ - name: HeadRequests
+ statistics: [Sum]
+ - name: PostRequests
+ statistics: [Sum]
+ - name: ListRequests
+ statistics: [Sum]
+ - name: BytesDownloaded
+ statistics: [Sum]
+ - name: BytesUploaded
+ statistics: [Sum]
+ - name: 4xxErrors
+ statistics: [Sum]
+ - name: 5xxErrors
+ statistics: [Sum]
+ - name: FirstByteLatency
+ statistics: [Minimum, Maximum, Average]
+ - name: TotalRequestLatency
+ statistics: [Minimum, Maximum, Average]
+ - name: ReplicationLatency
+ statistics: [Maximum]
+ - name: BytesPendingReplication
+ statistics: [Maximum]
+ - name: OperationsPendingReplication
+ statistics: [Maximum]
+ - name: OperationsFailedReplication
+ statistics: [Sum]
+ - type: AWS/EC2
+ regions:
+ - us-east-2
+ roles:
+ - roleArn: "arn:aws:iam::683740446523:role/osm-cloudwatch-export-role" # osm-render
+ period: 300
+ length: 300
+ metrics:
+ - name: CPUUtilization
+ statistics: [Average]
+ - name: DiskReadOps
+ statistics: [Sum]
+ - name: DiskWriteOps
+ statistics: [Sum]
+ - name: DiskReadBytes
+ statistics: [Sum]
+ - name: DiskWriteBytes
+ statistics: [Sum]
+ - name: NetworkIn
+ statistics: [Sum]
+ - name: NetworkOut
+ statistics: [Sum]
+ - name: NetworkPacketsIn
+ statistics: [Sum]
+ - name: NetworkPacketsOut
+ statistics: [Sum]
+ - type: AWS/Billing
+ regions:
+ - us-east-1
+ roles:
+ - roleArn: "arn:aws:iam::173189593406:role/osm-cloudwatch-export-role" # osm-main
+ - roleArn: "arn:aws:iam::674083635870:role/osm-cloudwatch-export-role" # osm-backup
+ - roleArn: "arn:aws:iam::683740446523:role/osm-cloudwatch-export-role" # osm-render
+ # Note osm-planet is billed direct to AWS Open Data Program
+ period: 21600
+ length: 21600
+ metrics:
+ - name: EstimatedCharges
+ statistics: [Sum]
+static:
+ - namespace: AWS/S3
+ name: gps-images-replication
+ regions:
+ - eu-north-1
+ roles:
+ - roleArn: "arn:aws:iam::173189593406:role/osm-cloudwatch-export-role" # osm-main
+ dimensions:
+ - name: RuleId
+ value: full-bucket-replication
+ - name: SourceBucket
+ value: openstreetmap-gps-images
+ - name: DestinationBucket
+ value: openstreetmap-gps-images-replicate
+ metrics:
+ - name: ReplicationLatency
+ statistics: [Maximum]
+ period: 300
+ length: 300
+ - name: BytesPendingReplication
+ statistics: [Maximum]
+ period: 300
+ length: 300
+ - name: OperationsPendingReplication
+ statistics: [Maximum]
+ period: 300
+ length: 300
+ - namespace: AWS/S3
+ name: gps-traces-replication
+ regions:
+ - eu-north-1
+ roles:
+ - roleArn: "arn:aws:iam::173189593406:role/osm-cloudwatch-export-role" # osm-main
+ dimensions:
+ - name: RuleId
+ value: full-bucket-replication
+ - name: SourceBucket
+ value: openstreetmap-gps-traces
+ - name: DestinationBucket
+ value: openstreetmap-gps-traces-replicate
+ metrics:
+ - name: ReplicationLatency
+ statistics: [Maximum]
+ period: 300
+ length: 300
+ - name: BytesPendingReplication
+ statistics: [Maximum]
+ period: 300
+ length: 300
+ - name: OperationsPendingReplication
+ statistics: [Maximum]
+ period: 300
+ length: 300
+ - namespace: AWS/S3
+ name: user-avatars-replication
+ regions:
+ - eu-north-1
+ roles:
+ - roleArn: "arn:aws:iam::173189593406:role/osm-cloudwatch-export-role" # osm-main
+ dimensions:
+ - name: RuleId
+ value: full-bucket-replication
+ - name: SourceBucket
+ value: openstreetmap-user-avatars
+ - name: DestinationBucket
+ value: openstreetmap-user-avatars-replicate
+ metrics:
+ - name: ReplicationLatency
+ statistics: [Maximum]
+ period: 300
+ length: 300
+ - name: BytesPendingReplication
+ statistics: [Maximum]
+ period: 300
+ length: 300
+ - name: OperationsPendingReplication
+ statistics: [Maximum]
+ period: 300
+ length: 300
+ - namespace: AWS/S3
+ name: aws-cloudtrail-replication
+ regions:
+ - eu-north-1
+ roles:
+ - roleArn: "arn:aws:iam::173189593406:role/osm-cloudwatch-export-role" # osm-main
+ dimensions:
+ - name: RuleId
+ value: full-bucket-replication
+ - name: SourceBucket
+ value: openstreetmap-aws-cloudtrail
+ - name: DestinationBucket
+ value: openstreetmap-aws-cloudtrail-replicate
+ metrics:
+ - name: ReplicationLatency
+ statistics: [Maximum]
+ period: 300
+ length: 300
+ - name: BytesPendingReplication
+ statistics: [Maximum]
+ period: 300
+ length: 300
+ - name: OperationsPendingReplication
+ statistics: [Maximum]
+ period: 300
+ length: 300
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-ARGS="--web.external-url=https://prometheus.openstreetmap.org/alertmanager"
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-ARGS="--web.external-url=https://prometheus.openstreetmap.org/prometheus"
--- /dev/null
+exporter:
+ files:
+ - patterns:
+<% node[:prometheus][:files].each do |file| -%>
+ - <%= file %>
+<% end -%>
[security]
admin_user = admin
admin_password = <%= @passwords[:grafana_admin] %>
+disable_gravatar = true
+cookie_secure = true
[smtp]
enabled = true
--- /dev/null
+karma:
+ name: OpenStreetMap
+alertmanager:
+ interval: 1m
+ servers:
+ - name: openstreetmap
+ uri: http://127.0.0.1:9093/alertmanager/
+ external_uri: https://prometheus.openstreetmap.org/alertmanager/
+ proxy: true
+listen:
+ port: 8081
+ prefix: /karma/
+filters:
+ default:
+ - "@state=active"
+labels:
+ color:
+ static:
+ - instance
+ strip:
+ - "@cluster"
static_configs:
- targets:
- localhost:9093
- - job_name: promscale
- static_configs:
- - targets:
- - localhost:9201
- job_name: ssl
scrape_interval: 15m
metrics_path: /probe
replacement: 127.0.0.1:9219
<% @jobs.sort.each do |name, targets| -%>
- job_name: <%= name %>
+<% if targets.first[:scrape_interval] -%>
+ scrape_interval: <%= targets.first[:scrape_interval] %>
+<% end -%>
+<% if targets.first[:scrape_timeout] -%>
+ scrape_timeout: <%= targets.first[:scrape_timeout] %>
+<% end -%>
+<% if targets.first[:sni] -%>
+ tls_config:
+ server_name: <%= targets.first[:sni] %>
+ relabel_configs:
+ - target_label: __scheme__
+ replacement: https
+<% end -%>
static_configs:
<% targets.each do |target| -%>
- targets:
- "<%= target[:address] %>"
labels:
instance: <%= target[:instance] %>
+<% target[:labels].sort.each do |name, value| -%>
+ <%= name %>: <%= value %>
+<% end -%>
<% end -%>
metric_relabel_configs:
<% targets.each do |target| -%>
<% end -%>
<% end -%>
<% end -%>
+ - job_name: junos
+ scrape_interval: 5m
+ scrape_timeout: 4m
+ static_configs:
+<% @junos_targets.sort_by { |t| t[:instance] }.each do |target| -%>
+ - targets:
+ - "<%= target[:target] %>/<%= target[:address] %>"
+ labels:
+ instance: <%= target[:instance] %>
+<% target[:labels].sort.each do |name, value| -%>
+ <%= name %>: <%= value %>
+<% end -%>
+<% end -%>
+ relabel_configs:
+ - source_labels: [__address__]
+ regex: "([^/]+)/.*"
+ target_label: __param_target
+ - source_labels: [__address__]
+ regex: "[^/]+/(.*)"
+ target_label: __address__
- job_name: snmp
scrape_interval: 5m
- scrape_timeout: 1m
+ scrape_timeout: 2m
metrics_path: /snmp
static_configs:
- - targets:
<% @snmp_targets.sort_by { |t| t[:instance] }.each do |target| -%>
- targets:
- - "<%= target[:target] %>/<%= target[:module] %>/<%= target[:address] %>"
+<% target[:modules].each do |module_name| -%>
+ - "<%= target[:target] %>/<%= module_name %>/<%= target[:address] %>"
+<% end -%>
labels:
instance: <%= target[:instance] %>
<% target[:labels].sort.each do |name, value| -%>
- source_labels: [__address__]
regex: "[^/]+/([^/]+)/.*"
target_label: __param_module
+ - source_labels: [__address__]
+ regex: "[^/]+/([^/]+)/.*"
+ target_label: module
- source_labels: [__address__]
regex: "[^/]+/[^/]+/(.*)"
target_label: __address__
-
-remote_write:
- - url: "http://localhost:9201/write"
- write_relabel_configs:
- - source_labels: [__name__]
- regex: "go_.*"
- action: drop
- - source_labels: [__name__]
- regex: "promhttp_.*"
- action: drop
- queue_config:
- capacity: 10000
- min_shards: 4
- batch_send_deadline: 30s
- max_backoff: 1s
--- /dev/null
+---
+targets:
+- hosts:
+<% @ip4_hosts.sort.each do |host| -%>
+ - <%= host %>
+<% end -%>
+ interval: 5s
+ network: ip4
+ size: 24
+- hosts:
+<% @ip6_hosts.sort.each do |host| -%>
+ - <%= host %>
+<% end -%>
+ interval: 5s
+ network: ip6
+ size: 24
# limitations under the License.
#
-if node[:lsb][:release].to_f < 20.04
- package "python"
- package "python-pip"
-end
-
package "python3"
package "python3-pip"
end
end
+action :upgrade do
+ if new_resource.version.nil?
+ execute "pip-upgrade-#{new_resource.package_name}" do
+ command "#{pip_command} install --upgrade #{new_resource.package_name}"
+ only_if "#{pip_command} list --outdated | fgrep -q #{new_resource.package_name}"
+ end
+ else
+ execute "pip-upgrade-#{new_resource.package_name}" do
+ command "#{pip_command} install --upgrade #{new_resource.package_name}==#{new_resource.version}"
+ not_if "#{pip_command} show #{new_resource.package_name} | fgrep -q #{new_resource.version}"
+ end
+ end
+end
+
action :remove do
execute "pip-uninstall-#{new_resource.package_name}" do
command "#{pip_command} uninstall #{new_resource.package_name}"
include_recipe "networking"
+writable_paths = []
hosts_allow = {}
hosts_deny = {}
node[:rsyncd][:modules].each do |name, details|
+ writable_paths << details[:path] if details[:write_only]
+
hosts_allow[name] = details[:hosts_allow] || []
if details[:nodes_allow]
systemd_service "rsync-override" do
service "rsync"
dropin "override"
- exec_start "/usr/bin/rsync --daemon --no-detach --bwlimit=16384"
+ exec_start "/usr/bin/rsync --daemon --no-detach"
+ nice 10
+ read_write_paths writable_paths.sort
notifies :restart, "service[rsync]"
end
firewall_rule "accept-rsync" do
action :accept
- source "net"
- dest "fw"
- proto "tcp:syn"
+ context :incoming
+ protocol :tcp
dest_ports "rsync"
- source_ports "1024:"
+ source_ports "1024-65535"
end
--- /dev/null
+# Ruby Cookbook
+
+Installs and configures ruby.
--- /dev/null
+default[:ruby][:version] = if platform?("debian")
+ "3.1"
+ elsif node[:lsb][:release].to_f < 22.04
+ "2.7"
+ else
+ "3.0"
+ end
+default[:ruby][:gem] = "/usr/bin/gem#{node[:ruby][:version]}"
+default[:ruby][:bundle] = "/usr/bin/bundle#{node[:ruby][:version]}"
-name "incron"
+name "ruby"
maintainer "OpenStreetMap Administrators"
maintainer_email "admins@openstreetmap.org"
license "Apache-2.0"
-description "Configures incron"
+description "Installs and configures ruby"
version "1.0.0"
supports "ubuntu"
--- /dev/null
+#
+# Cookbook:: ruby
+# Recipe:: default
+#
+# Copyright:: 2022, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+ruby_version = node[:ruby][:version]
+
+package %W[
+ ruby
+ ruby#{ruby_version}
+ ruby
+ ruby#{ruby_version}-dev
+]
+
+gem_package "bundler#{ruby_version}-1" do
+ package_name "bundler"
+ version "~> 1.17.3"
+ gem_binary node[:ruby][:gem]
+ options "--format-executable"
+end
+
+gem_package "bundler#{ruby_version}-2" do
+ package_name "bundler"
+ version "~> 2.3.16"
+ gem_binary node[:ruby][:gem]
+ options "--format-executable"
+end
--- /dev/null
+#
+# Cookbook:: ruby
+# Resource:: bundle_exec
+#
+# Copyright:: 2022, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+resource_name :bundle_exec
+provides :bundle_exec
+
+unified_mode true
+
+default_action :run
+
+property :directory, :kind_of => String, :name_property => true
+property :command, :kind_of => String
+property :user, :kind_of => String
+property :group, :kind_of => String
+property :environment, :kind_of => Hash
+
+action :run do
+ execute "#{new_resource.directory}/Gemfile" do
+ command "#{bundle_command} exec #{new_resource.command}"
+ cwd new_resource.directory
+ user new_resource.user
+ group new_resource.group
+ environment new_resource.environment
+ end
+end
+
+action_class do
+ def bundle_command
+ node[:ruby][:bundle]
+ end
+end
--- /dev/null
+#
+# Cookbook:: ruby
+# Resource:: bundle_install
+#
+# Copyright:: 2022, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+resource_name :bundle_install
+provides :bundle_install
+
+unified_mode true
+
+default_action :run
+
+property :directory, :kind_of => String, :name_property => true
+property :options, :kind_of => String
+property :user, :kind_of => String
+property :group, :kind_of => String
+property :environment, :kind_of => Hash
+
+action :run do
+ execute "#{new_resource.directory}/Gemfile" do
+ command "#{bundle_command} install #{new_resource.options}"
+ cwd new_resource.directory
+ user new_resource.user
+ group new_resource.group
+ environment new_resource.environment
+ end
+end
+
+action_class do
+ def bundle_command
+ node[:ruby][:bundle]
+ end
+end
+
+def after_created
+ subscribes :run, "gem_package[bundler#{node[:ruby][:version]}-1]"
+ subscribes :run, "gem_package[bundler#{node[:ruby][:version]}-2]"
+end
This cookbook configures the hardware details website found at
[hardware.openstreetmap.org](https://hardware.openstreetmap.org). The code for
-the website itself is available at [github.com/gravitystorm/osmf-server-info](https://github.com/gravitystorm/osmf-server-info).
+the website itself is available at [github.com/osmfoundation/osmf-server-info](https://github.com/osmfoundation/osmf-server-info).
supports "ubuntu"
depends "apache"
depends "git"
+depends "ruby"
include_recipe "apache"
include_recipe "git"
+include_recipe "ruby"
package %w[
gcc
g++
make
- ruby
- ruby-dev
libssl-dev
zlib1g-dev
pkg-config
]
-gem_package "bundler" do
- version "1.17.3"
-end
-
git "/srv/hardware.openstreetmap.org" do
action :sync
- repository "https://github.com/gravitystorm/osmf-server-info.git"
+ repository "https://github.com/osmfoundation/osmf-server-info.git"
depth 1
user "root"
group "root"
- notifies :run, "execute[/srv/hardware.openstreetmap.org/Gemfile]"
+ notifies :run, "bundle_install[/srv/hardware.openstreetmap.org]"
end
nodes = { :rows => search(:node, "*:*") }
mode "644"
owner "root"
group "root"
- notifies :run, "execute[/srv/hardware.openstreetmap.org]"
+ notifies :run, "bundle_exec[/srv/hardware.openstreetmap.org]"
end
file "/srv/hardware.openstreetmap.org/_data/roles.json" do
mode "644"
owner "root"
group "root"
- notifies :run, "execute[/srv/hardware.openstreetmap.org]"
+ notifies :run, "bundle_exec[/srv/hardware.openstreetmap.org]"
end
directory "/srv/hardware.openstreetmap.org/_site" do
group "nogroup"
end
-# Workaround https://github.com/jekyll/jekyll/issues/7804
-# by creating a .jekyll-cache folder
-directory "/srv/hardware.openstreetmap.org/.jekyll-cache" do
- mode "755"
+directory "/srv/hardware.openstreetmap.org/vendor" do
+ action :create
owner "nobody"
group "nogroup"
+ notifies :run, "bundle_install[/srv/hardware.openstreetmap.org]", :immediately
end
-execute "/srv/hardware.openstreetmap.org/Gemfile" do
+bundle_install "/srv/hardware.openstreetmap.org" do
action :nothing
- command "bundle install --deployment"
- cwd "/srv/hardware.openstreetmap.org"
- user "root"
- group "root"
- notifies :run, "execute[/srv/hardware.openstreetmap.org]"
+ user "nobody"
+ group "nogroup"
+ environment "BUNDLE_FROZEN" => "true",
+ "BUNDLE_WITHOUT" => "development:test",
+ "BUNDLE_PATH" => "vendor/bundle",
+ "BUNDLE_DEPLOYMENT" => "1",
+ "BUNDLE_JOBS" => node.cpu_cores.to_s
+ notifies :run, "bundle_exec[/srv/hardware.openstreetmap.org]"
end
-execute "/srv/hardware.openstreetmap.org" do
+bundle_exec "/srv/hardware.openstreetmap.org" do
action :nothing
- command "bundle exec jekyll build --trace --baseurl=https://hardware.openstreetmap.org"
- cwd "/srv/hardware.openstreetmap.org"
+ command "jekyll build --trace --disable-disk-cache --baseurl=https://hardware.openstreetmap.org"
user "nobody"
group "nogroup"
+ environment "LANG" => "C.UTF-8",
+ "BUNDLE_PATH" => "vendor/bundle",
+ "BUNDLE_DEPLOYMENT" => "1"
end
ssl_certificate "hardware.openstreetmap.org" do
- domains ["hardware.openstreetmap.org", "hardware.osm.org"]
+ domains ["hardware.openstreetmap.org", "hardware.osm.org", "hardware.osmfoundation.org"]
notifies :reload, "service[apache2]"
end
apache_site "hardware.openstreetmap.org" do
template "apache.erb"
directory "/srv/hardware.openstreetmap.org/_site"
- variables :aliases => ["hardware.osm.org"]
+ variables :aliases => ["hardware.osm.org", "hardware.osmfoundation.org"]
end
<% end -%>
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
RedirectPermanent / https://<%= @name %>/
ServerName <%= @name %>
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
SSLEngine on
package "snmpd"
-service "snmpd" do
- action [:enable, :start]
- supports :status => true, :restart => true
-end
-
template "/etc/snmp/snmpd.conf" do
source "snmpd.conf.erb"
owner "root"
notifies :restart, "service[snmpd]"
end
-if node[:snmpd][:clients]
- node[:snmpd][:clients].each do |address|
- firewall_rule "accept-snmp" do
- action :accept
- family "inet"
- source "net:#{address}"
- dest "fw"
- proto "udp"
- dest_ports "snmp"
- source_ports "1024:"
- end
- end
-else
- firewall_rule "accept-snmp" do
- action :accept
- family "inet"
- source "net"
- dest "fw"
- proto "udp"
- dest_ports "snmp"
- source_ports "1024:"
- end
+service "snmpd" do
+ action [:enable, :start]
+ supports :status => true, :restart => true
end
-if node[:snmpd][:clients6]
- node[:snmpd][:clients6].each do |address|
- firewall_rule "accept-snmp" do
- action :accept
- family "inet6"
- source "net:#{address}"
- dest "fw"
- proto "udp"
- dest_ports "snmp"
- source_ports "1024:"
- end
- end
-else
- firewall_rule "accept-snmp" do
- action :accept
- family "inet6"
- source "net"
- dest "fw"
- proto "udp"
- dest_ports "snmp"
- source_ports "1024:"
- end
+firewall_rule "accept-snmp" do
+ action :accept
+ context :incoming
+ protocol :udp
+ source node[:snmpd][:clients] if node[:snmpd][:clients]
+ dest_ports "snmp"
+ source_ports "1024-65535"
end
package "spamassassin"
-service "spamassassin" do
+service_name = if platform?("debian")
+ "spamd"
+ else
+ "spamassassin"
+ end
+
+service service_name do
action [:enable, :start]
supports :status => true, :restart => true, :reload => true
end
owner "root"
group "root"
mode "644"
- notifies :restart, "service[spamassassin]"
+ notifies :restart, "service[#{service_name}]"
end
trusted_networks = node[:exim][:relay_from_hosts]
group "root"
mode "644"
variables :trusted_networks => trusted_networks.sort
- notifies :restart, "service[spamassassin]"
+ notifies :restart, "service[#{service_name}]"
end
+++ /dev/null
-# Squid cookbook
-
-This cookbook installs the Squid caching proxy service and configures it for use
-as a tile cache.
+++ /dev/null
-default[:squid][:version] = 4
-default[:squid][:cache_mem] = "256 MB"
-default[:squid][:cache_dir] = "ufs /var/spool/squid 256 16 256"
-default[:squid][:access_log] = "/var/log/squid/access.log openstreetmap"
-default[:squid][:private_devices] = true
-
-default[:apt][:sources] = node[:apt][:sources] | ["squid#{node[:squid][:version]}"]
+++ /dev/null
-#
-# Cookbook:: squid
-# Recipe:: default
-#
-# Copyright:: 2011, OpenStreetMap Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-include_recipe "apt"
-include_recipe "munin"
-include_recipe "prometheus"
-
-if node[:squid][:version] >= 3
- apt_package "squid" do
- action :unlock
- end
-
- apt_package "squid-common" do
- action :unlock
- end
-
- apt_package "squid" do
- action :purge
- only_if "dpkg-query -W squid | fgrep -q 2."
- end
-
- apt_package "squid-common" do
- action :purge
- only_if "dpkg-query -W squid-common | fgrep -q 2."
- end
-
- file "/store/squid/coss-01" do
- action :delete
- backup false
- end
-
- package "squidclient" do
- action :upgrade
- end
-end
-
-package "squid"
-package "squidclient"
-
-template "/etc/squid/squid.conf" do
- source "squid.conf.erb"
- owner "root"
- group "root"
- mode "644"
-end
-
-directory "/etc/squid/squid.conf.d" do
- owner "root"
- group "root"
- mode "755"
-end
-
-Array(node[:squid][:cache_dir]).each do |cache_dir|
- if cache_dir =~ /^coss (\S+) /
- cache_dir = File.dirname(Regexp.last_match(1))
- elsif cache_dir =~ /^\S+ (\S+) /
- cache_dir = Regexp.last_match(1)
- end
-
- directory cache_dir do
- owner "proxy"
- group "proxy"
- mode "750"
- recursive true
- notifies :restart, "service[squid]"
- end
-end
-
-systemd_tmpfile "/var/run/squid" do
- type "d"
- owner "proxy"
- group "proxy"
- mode "0755"
-end
-
-address_families = %w[AF_UNIX AF_INET AF_INET6]
-
-file "/etc/systemd/system/squid.service" do
- action :delete
-end
-
-file "/etc/logrotate.d/squid.dpkg-dist" do
- action :delete
-end
-
-squid_service_exec = if node[:lsb][:release].to_f < 20.04
- "/usr/sbin/squid -YC"
- else
- "/usr/sbin/squid --foreground -YC"
- end
-
-systemd_service "squid" do
- dropin "chef"
- limit_nofile 98304
- private_tmp true
- private_devices node[:squid][:private_devices]
- protect_system "full"
- protect_home true
- restrict_address_families address_families
- restart "always"
- exec_start "#{squid_service_exec}"
-end
-
-service "squid" do
- action :enable
- subscribes :restart, "systemd_service[squid]"
- subscribes :restart, "template[/etc/squid/squid.conf]"
- subscribes :reload, "template[/etc/resolv.conf]"
-end
-
-notify_group "squid-start" do
- action :run
- notifies :start, "service[squid]"
-end
-
-service "squid-restart" do
- service_name "squid"
- action :restart
- only_if do
- IO.popen(["squidclient", "--host=127.0.0.1", "--port=3128", "mgr:counters"]) do |io|
- io.each.grep(/^[a-z][a-z_.]+ = -[0-9]+$/).count.positive?
- end
- end
-end
-
-munin_plugin "squid_cache"
-munin_plugin "squid_times"
-munin_plugin "squid_icp"
-munin_plugin "squid_objectsize"
-munin_plugin "squid_requests"
-munin_plugin "squid_traffic"
-
-munin_plugin "squid_delay_pools" do
- action :delete
-end
-
-munin_plugin "squid_delay_pools_noreferer" do
- action :delete
-end
-
-prometheus_exporter "squid" do
- port 9301
- listen_switch "listen"
-end
+++ /dev/null
-#
-# Cookbook:: squid
-# Resource:: squid_fragment
-#
-# Copyright:: 2015, OpenStreetMap Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-unified_mode true
-
-default_action :create
-
-property :fragment, :kind_of => String, :name_property => true
-property :template, :kind_of => String, :required => [:create]
-property :variables, :kind_of => Hash, :default => {}
-
-action :create do
- declare_resource :template, fragment_path do
- source new_resource.template
- owner "root"
- group "root"
- mode "644"
- variables new_resource.variables
- end
-end
-
-action :delete do
- file fragment_path do
- action :delete
- end
-end
-
-action_class do
- def fragment_path
- "/etc/squid/squid.conf.d/#{new_resource.fragment}.conf"
- end
-end
-
-def after_created
- notifies :create, "template[/etc/squid/squid.conf]"
-end
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-# configure host name
-visible_hostname <%= node.name %>
-
-cache_mem <%= node[:squid][:cache_mem] %>
-<% if node[:squid][:version] > 2 -%>
-
-workers <%= [ node[:cpu][:total] - 2, 1 ].max.ceil %>
-cpu_affinity_map process_numbers=<%= (1..[ node[:cpu][:total] - 2, 1 ].max.ceil).to_a.join(',') %> cores=<%=(1..[ node[:cpu][:total] - 2, 1 ].max.ceil).to_a.join(',') %>
-
-# Set short clean shutdown interval
-shutdown_lifetime 2 seconds
-
-error_log_languages off
-<% end -%>
-
-max_filedescriptors 98304
-
-<% if node[:squid][:version] > 3 -%>
-# Use RFC6891 recommended max size
-dns_packet_max 4096 bytes
-# Use low initial retry interval (backoff start)
-dns_retransmit_interval 2 seconds
-# Set low timeout
-dns_timeout 15 seconds
-<% end -%>
-dns_v4_first on
-
-# used by squidclient / munin
-http_port 3128
-# HTCP
-htcp_port 4827
-# ICP
-icp_port 3130
-log_icp_queries off
-
-<% if node[:squid][:version] < 3 -%>
-http_port 80 accel defaultsite=tile.openstreetmap.org tcpkeepalive=60,10,6 http11
-<% else -%>
-http_port 8080 accel no-vhost defaultsite=tile.openstreetmap.org tcpkeepalive=60,10,6
-<% end -%>
-
-cache_effective_user proxy
-cache_effective_group proxy
-
-<% Array(node[:squid][:cache_dir]).each do |cache_dir| -%>
-cache_dir <%= cache_dir %>
-<% end -%>
-
-<% if node[:squid][:version] < 3 -%>
-cache_swap_log /var/spool/squid/%s
-<% end -%>
-
-cache_mgr webmaster@openstreetmap.org
-
-quick_abort_min 0 KB
-quick_abort_max 0 KB
-
-read_ahead_gap 64 KB
-
-maximum_object_size 256 KB
-maximum_object_size_in_memory 64 KB
-
-cache_replacement_policy heap LFUDA
-memory_replacement_policy heap GDSF
-
-server_persistent_connections on
-<% if node[:squid][:version] < 3 -%>
-persistent_request_timeout 1 minutes
-<% else -%>
-client_idle_pconn_timeout 1 minutes
-<% end -%>
-<% if node[:squid][:version] > 3 -%>
-pconn_lifetime 5 minutes
-<% end -%>
-
-negative_ttl 15 seconds
-<% if node[:squid][:version] < 3 -%>
-pipeline_prefetch on
-<% end -%>
-
-read_timeout 90 seconds
-request_timeout 90 seconds
-connect_timeout 20 seconds
-client_lifetime 1 hours
-
-<% if node[:squid][:version] < 3 -%>
-refresh_stale_hit 300 seconds
-<% end -%>
-
-# Recommended minimum configuration:
-# ----------------------------------
-<% if node[:squid][:version] < 3 -%>
-acl all src all
-acl manager proto cache_object
-acl localhost src 127.0.0.1/32
-acl to_localhost dst 127.0.0.0/8
-<% end -%>
-acl SSL_ports port 443
-acl Safe_ports port 80 # http
-acl Safe_ports port 21 # ftp
-acl Safe_ports port 443 # https
-acl Safe_ports port 70 # gopher
-acl Safe_ports port 210 # wais
-acl Safe_ports port 1025-65535 # unregistered ports
-acl Safe_ports port 280 # http-mgmt
-acl Safe_ports port 488 # gss-http
-acl Safe_ports port 591 # filemaker
-acl Safe_ports port 777 # multiling http
-acl CONNECT method CONNECT
-http_access allow manager localhost
-
-http_access allow manager
-
-http_access deny manager
-http_access deny !Safe_ports
-http_access deny CONNECT !SSL_ports
-# ----------------------------------
-
-acl purge_hosts src 127.0.0.0/8
-acl PURGE method purge
-http_access allow purge purge_hosts
-http_access deny purge
-
-forwarded_for on
-follow_x_forwarded_for allow localhost
-
-<% if node[:squid][:version] < 3 -%>
-logformat openstreetmap %ts.%03tu %tr %>a %Ss/%03Hs %<st %rm %rp %Sh/%<A %mt "%{Referer}>h" "%{User-Agent}>h"
-access_log <%= node[:squid][:access_log] %>
-<% else -%>
-logformat openstreetmap %ts.%03tu %tr %>a %Ss/%03>Hs %<st %rm %>rp %Sh/%<A %mt "%{Referer}>h" "%{User-Agent}>h"
-access_log daemon:<%= node[:squid][:access_log] %>
-<% end -%>
-cache_log /var/log/squid/cache.log
-cache_store_log none
-
-buffered_logs on
-
-client_db off
-strip_query_terms off
-<% if node[:squid][:version] > 2 -%>
-# Work around bug in squid 3 that causes log_fqdn to be
-# turned on by some of the (unused by us) default formats:
-# http://lists.squid-cache.org/pipermail/squid-users/2016-February/thread.html#8999
-url_rewrite_extras "%>a %un %>rm myip=%la myport=%lp"
-store_id_extras "%>a %un %>rm myip=%la myport=%lp"
-<% end -%>
-
-digest_generation off
-
-refresh_pattern . 0 50% 20160
-refresh_pattern -i tile.openstreetmap.org 60 80% 20160 reload-into-ims
-
-# ZERO required for logrotate to work properly
-logfile_rotate 0
-
-<% Dir.glob("/etc/squid/squid.conf.d/*.conf") do |file| -%>
-<%= File.read(file) %>
-<% end -%>
-
-# MUST BE LAST ACL
-# --------------
-http_access deny all
-htcp_access deny all
-icp_access deny all
-# --------------
default[:ssl][:openssl_ciphers] = "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS"
-default[:ssl][:gnutls_ciphers] = "NONE:+AEAD:+SHA256:+SHA1:+SHA384:+SHA512:+CURVE-X25519:+CURVE-SECP256R1:+CURVE-SECP384R1:+CURVE-SECP521R1:+SIGN-ALL:-SIGN-RSA-MD5:-SIGN-DSA-SHA1:-SIGN-DSA-SHA224:-SIGN-DSA-SHA256:-SIGN-DSA-SHA384:-SIGN-DSA-SHA512:+AES-256-GCM:+AES-256-CCM:+CHACHA20-POLY1305:+CAMELLIA-256-GCM:+AES-256-CBC:+CAMELLIA-256-CBC:+AES-128-GCM:+AES-128-CCM:+CAMELLIA-128-GCM:+AES-128-CBC:+CAMELLIA-128-CBC:+ECDHE-RSA:+ECDHE-ECDSA:+RSA:+DHE-RSA:+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0:+VERS-DTLS1.2:+VERS-DTLS1.0:+COMP-NULL:%PROFILE_LOW"
+default[:ssl][:gnutls_ciphers] = "NONE:+AEAD:+SHA256:+SHA1:+SHA384:+SHA512:+CURVE-X25519:+CURVE-SECP256R1:+CURVE-SECP384R1:+CURVE-SECP521R1:+SIGN-ALL:-SIGN-RSA-MD5:-SIGN-DSA-SHA1:-SIGN-DSA-SHA224:-SIGN-DSA-SHA256:-SIGN-DSA-SHA384:-SIGN-DSA-SHA512:+AES-256-GCM:+AES-256-CCM:+CHACHA20-POLY1305:+CAMELLIA-256-GCM:+AES-256-CBC:+CAMELLIA-256-CBC:+AES-128-GCM:+AES-128-CCM:+CAMELLIA-128-GCM:+AES-128-CBC:+CAMELLIA-128-CBC:+ECDHE-RSA:+ECDHE-ECDSA:+RSA:+DHE-RSA:+VERS-TLS1.3:+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0:+VERS-DTLS1.2:+VERS-DTLS1.0:+COMP-NULL:%PROFILE_LOW"
default[:ssl][:strict_transport_security] = "max-age=31536000; includeSubDomains; preload"
default[:ssl][:ct_report_uri] = "https://openstreetmap.report-uri.com/r/d/ct/reportOnly"
version "1.0.0"
supports "ubuntu"
+depends "apache"
+depends "podman"
depends "wordpress"
--- /dev/null
+#
+# Cookbook:: stateofthemap
+# Recipe:: container
+#
+# Copyright:: 2022, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "podman::apache"
+
+podman_site "stateofthemap.org" do
+ image "ghcr.io/openstreetmap/stateofthemap-website:latest"
+ aliases ["www.stateofthemap.org", "stateofthemap.com", "www.stateofthemap.com", "sotm.org", "www.sotm.org"]
+end
+
+%w[2013 2016 2017 2018 2019 2020 2021 2022 2024].each do |year|
+ podman_site "#{year}.stateofthemap.org" do
+ image "ghcr.io/openstreetmap/stateofthemap-#{year}:latest"
+ aliases ["#{year}.stateofthemap.com", "#{year}.sotm.org"]
+ end
+end
# See the License for the specific language governing permissions and
# limitations under the License.
#
-
-include_recipe "wordpress"
-
-passwords = data_bag_item("stateofthemap", "passwords")
-
-git "/srv/stateofthemap.org" do
- action :sync
- repository "https://git.openstreetmap.org/public/stateofthemap.git"
- revision "chooser"
- depth 1
- user "root"
- group "root"
-end
-
-ssl_certificate "stateofthemap.org" do
- domains ["stateofthemap.org", "www.stateofthemap.org",
- "stateofthemap.com", "www.stateofthemap.com",
- "sotm.org", "www.sotm.org"]
- notifies :reload, "service[apache2]"
-end
-
-apache_site "stateofthemap.org" do
- template "apache.erb"
- directory "/srv/stateofthemap.org"
-end
-
-directory "/srv/2007.stateofthemap.org" do
- owner "wordpress"
- group "wordpress"
- mode "755"
-end
-
-wordpress_site "2007.stateofthemap.org" do
- aliases "2007.stateofthemap.com"
- directory "/srv/2007.stateofthemap.org/wp"
- database_name "sotm2007"
- database_user "sotm2007"
- database_password passwords["sotm2007"]
- database_prefix "wp_sotm_"
- fpm_prometheus_port 12007
-end
-
-wordpress_theme "2007.stateofthemap.org-refreshwp-11" do
- theme "refreshwp-11"
- site "2007.stateofthemap.org"
- repository "https://git.openstreetmap.org/public/stateofthemap.git"
- revision "theme-2007"
-end
-
-wordpress_plugin "2007.stateofthemap.org-geopress" do
- plugin "geopress"
- site "2007.stateofthemap.org"
-end
-
-directory "/srv/2008.stateofthemap.org" do
- owner "wordpress"
- group "wordpress"
- mode "755"
-end
-
-wordpress_site "2008.stateofthemap.org" do
- aliases "2008.stateofthemap.com"
- directory "/srv/2008.stateofthemap.org/wp"
- database_name "sotm2008"
- database_user "sotm2008"
- database_password passwords["sotm2008"]
- database_prefix "wp_sotm08_"
- fpm_prometheus_port 12008
-end
-
-wordpress_theme "2008.stateofthemap.org-refreshwp-11" do
- theme "refreshwp-11"
- site "2008.stateofthemap.org"
- repository "https://git.openstreetmap.org/public/stateofthemap.git"
- revision "theme-2008"
-end
-
-wordpress_plugin "2008.stateofthemap.org-geopress" do
- plugin "geopress"
- site "2008.stateofthemap.org"
-end
-
-directory "/srv/2009.stateofthemap.org" do
- owner "wordpress"
- group "wordpress"
- mode "755"
-end
-
-git "/srv/2009.stateofthemap.org" do
- action :sync
- repository "https://git.openstreetmap.org/public/stateofthemap.git"
- revision "resources-2009"
- depth 1
- user "wordpress"
- group "wordpress"
-end
-
-wordpress_site "2009.stateofthemap.org" do
- aliases "2009.stateofthemap.com"
- directory "/srv/2009.stateofthemap.org/wp"
- database_name "sotm2009"
- database_user "sotm2009"
- database_password passwords["sotm2009"]
- urls "/register" => "/srv/2009.stateofthemap.org/register",
- "/register-pro-user" => "/srv/2009.stateofthemap.org/register-pro-user",
- "/podcasts" => "/srv/2009.stateofthemap.org/podcasts"
- fpm_prometheus_port 12009
-end
-
-wordpress_theme "2009.stateofthemap.org-aerodrome" do
- theme "aerodrome"
- site "2009.stateofthemap.org"
- repository "https://git.openstreetmap.org/public/stateofthemap.git"
- revision "theme-2009"
-end
-
-wordpress_plugin "2009.stateofthemap.org-wp-sticky" do
- plugin "wp-sticky"
- site "2009.stateofthemap.org"
-end
-
-directory "/srv/2010.stateofthemap.org" do
- owner "wordpress"
- group "wordpress"
- mode "755"
-end
-
-git "/srv/2010.stateofthemap.org" do
- action :sync
- repository "https://git.openstreetmap.org/public/stateofthemap.git"
- revision "resources-2010"
- depth 1
- user "wordpress"
- group "wordpress"
-end
-
-wordpress_site "2010.stateofthemap.org" do
- aliases "2010.stateofthemap.com"
- directory "/srv/2010.stateofthemap.org/wp"
- database_name "sotm2010"
- database_user "sotm2010"
- database_password passwords["sotm2010"]
- urls "/register" => "/srv/2010.stateofthemap.org/register"
- fpm_prometheus_port 12010
-end
-
-wordpress_theme "2010.stateofthemap.org-aerodrome" do
- theme "aerodrome"
- site "2010.stateofthemap.org"
- repository "https://git.openstreetmap.org/public/stateofthemap.git"
- revision "theme-2010"
-end
-
-wordpress_plugin "2010.stateofthemap.org-sitepress-multilingual-cms" do
- plugin "sitepress-multilingual-cms"
- site "2010.stateofthemap.org"
- repository "https://git.openstreetmap.org/private/sitepress-multilingual-cms.git"
- not_if { ENV["TEST_KITCHEN"] }
-end
-
-wordpress_plugin "2010.stateofthemap.org-wp-sticky" do
- plugin "wp-sticky"
- site "2010.stateofthemap.org"
-end
-
-directory "/srv/2011.stateofthemap.org" do
- owner "wordpress"
- group "wordpress"
- mode "755"
-end
-
-git "/srv/2011.stateofthemap.org" do
- action :sync
- repository "https://git.openstreetmap.org/public/stateofthemap.git"
- revision "resources-2011"
- depth 1
- user "wordpress"
- group "wordpress"
-end
-
-wordpress_site "2011.stateofthemap.org" do
- aliases "2011.stateofthemap.com"
- directory "/srv/2011.stateofthemap.org/wp"
- database_name "sotm2011"
- database_user "sotm2011"
- database_password passwords["sotm2011"]
- urls "/register" => "/srv/2011.stateofthemap.org/register"
- fpm_prometheus_port 12011
-end
-
-wordpress_theme "2011.stateofthemap.org-aerodrome" do
- theme "aerodrome"
- site "2011.stateofthemap.org"
- repository "https://git.openstreetmap.org/public/stateofthemap.git"
- revision "theme-2011"
-end
-
-wordpress_plugin "2011.stateofthemap.org-sitepress-multilingual-cms" do
- plugin "sitepress-multilingual-cms"
- site "2011.stateofthemap.org"
- repository "https://git.openstreetmap.org/private/sitepress-multilingual-cms.git"
- not_if { ENV["TEST_KITCHEN"] }
-end
-
-wordpress_plugin "2011.stateofthemap.org-wp-sticky" do
- plugin "wp-sticky"
- site "2011.stateofthemap.org"
-end
-
-directory "/srv/2012.stateofthemap.org" do
- owner "wordpress"
- group "wordpress"
- mode "755"
-end
-
-git "/srv/2012.stateofthemap.org" do
- action :sync
- repository "https://git.openstreetmap.org/public/stateofthemap.git"
- revision "resources-2012"
- depth 1
- user "wordpress"
- group "wordpress"
-end
-
-wordpress_site "2012.stateofthemap.org" do
- aliases "2012.stateofthemap.com"
- directory "/srv/2012.stateofthemap.org/wp"
- database_name "sotm2012"
- database_user "sotm2012"
- database_password passwords["sotm2012"]
- urls "/register" => "/srv/2012.stateofthemap.org/register"
- fpm_prometheus_port 12012
-end
-
-wordpress_theme "2012.stateofthemap.org-aerodrome" do
- theme "aerodrome"
- site "2012.stateofthemap.org"
- repository "https://git.openstreetmap.org/public/stateofthemap.git"
- revision "theme-2012"
-end
-
-wordpress_plugin "2012.stateofthemap.org-leaflet-maps-marker" do
- plugin "leaflet-maps-marker"
- site "2012.stateofthemap.org"
-end
-
-wordpress_plugin "2012.stateofthemap.org-sitepress-multilingual-cms" do
- plugin "sitepress-multilingual-cms"
- site "2012.stateofthemap.org"
- repository "https://git.openstreetmap.org/private/sitepress-multilingual-cms.git"
- not_if { ENV["TEST_KITCHEN"] }
-end
-
-wordpress_plugin "2012.stateofthemap.org-wp-sticky" do
- plugin "wp-sticky"
- site "2012.stateofthemap.org"
-end
-
-%w[2013].each do |year|
- git "/srv/#{year}.stateofthemap.org" do
- action :sync
- repository "https://git.openstreetmap.org/public/stateofthemap.git"
- revision "site-#{year}"
- depth 1
- user "root"
- group "root"
- end
-
- ssl_certificate "#{year}.stateofthemap.org" do
- domains ["#{year}.stateofthemap.org", "#{year}.stateofthemap.com", "#{year}.sotm.org"]
- notifies :reload, "service[apache2]"
- end
-
- apache_site "#{year}.stateofthemap.org" do
- template "apache.static.erb"
- directory "/srv/#{year}.stateofthemap.org"
- variables :year => year
- end
-end
-
-package %w[
- gcc
- g++
- make
- ruby
- ruby-dev
- libssl-dev
- zlib1g-dev
- pkg-config
-]
-
-apache_module "expires"
-apache_module "rewrite"
-
-gem_package "bundler" do
- version "1.17.3"
-end
-
-gem_package "bundler" do
- version "2.1.4"
-end
-
-%w[2016 2017 2018 2019 2020 2021].each do |year|
- git "/srv/#{year}.stateofthemap.org" do
- action :sync
- repository "https://github.com/openstreetmap/stateofthemap-#{year}.git"
- depth 1
- user "root"
- group "root"
- notifies :run, "execute[/srv/#{year}.stateofthemap.org/Gemfile]"
- end
-
- directory "/srv/#{year}.stateofthemap.org/_site" do
- mode "755"
- owner "nobody"
- group "nogroup"
- end
-
- # Workaround https://github.com/jekyll/jekyll/issues/7804
- # by creating a .jekyll-cache folder
- directory "/srv/#{year}.stateofthemap.org/.jekyll-cache" do
- mode "755"
- owner "nobody"
- group "nogroup"
- end
-
- execute "/srv/#{year}.stateofthemap.org/Gemfile" do
- action :nothing
- command "bundle install --deployment --jobs #{node[:cpu][:total]}"
- cwd "/srv/#{year}.stateofthemap.org"
- user "root"
- group "root"
- notifies :run, "execute[/srv/#{year}.stateofthemap.org]"
- only_if { ::File.exist?("/srv/#{year}.stateofthemap.org/Gemfile") }
- end
-
- execute "/srv/#{year}.stateofthemap.org" do
- action :nothing
- command "bundle exec jekyll build --trace --baseurl=https://#{year}.stateofthemap.org"
- cwd "/srv/#{year}.stateofthemap.org"
- user "nobody"
- group "nogroup"
- end
-
- ssl_certificate "#{year}.stateofthemap.org" do
- domains ["#{year}.stateofthemap.org", "#{year}.stateofthemap.com", "#{year}.sotm.org"]
- notifies :reload, "service[apache2]"
- end
-
- apache_site "#{year}.stateofthemap.org" do
- template "apache.jekyll.erb"
- directory "/srv/#{year}.stateofthemap.org/_site"
- variables :year => year
- end
-end
-
-template "/etc/cron.daily/sotm-backup" do
- source "backup.cron.erb"
- owner "root"
- group "root"
- mode "750"
- variables :passwords => passwords
-end
--- /dev/null
+#
+# Cookbook:: stateofthemap
+# Recipe:: wordpress
+#
+# Copyright:: 2022, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "stateofthemap"
+include_recipe "wordpress"
+
+passwords = data_bag_item("stateofthemap", "passwords")
+wp2fa_encrypt_keys = data_bag_item("stateofthemap", "wp2fa_encrypt_keys")
+
+directory "/srv/2007.stateofthemap.org" do
+ owner "wordpress"
+ group "wordpress"
+ mode "755"
+end
+
+wordpress_site "2007.stateofthemap.org" do
+ aliases ["2007.stateofthemap.com", "2007.sotm.org"]
+ directory "/srv/2007.stateofthemap.org/wp"
+ database_name "sotm2007"
+ database_user "sotm2007"
+ database_password passwords["sotm2007"]
+ database_prefix "wp_sotm_"
+ wp2fa_encrypt_key wp2fa_encrypt_keys["sotm2007"]
+ fpm_prometheus_port 12007
+end
+
+wordpress_theme "2007.stateofthemap.org-refreshwp-11" do
+ theme "refreshwp-11"
+ site "2007.stateofthemap.org"
+ repository "https://git.openstreetmap.org/public/stateofthemap.git"
+ revision "theme-2007"
+end
+
+# Remove broken geopress plugin
+wordpress_plugin "2007.stateofthemap.org-geopress" do
+ action :delete
+ plugin "geopress"
+ site "2007.stateofthemap.org"
+end
+
+directory "/srv/2008.stateofthemap.org" do
+ owner "wordpress"
+ group "wordpress"
+ mode "755"
+end
+
+wordpress_site "2008.stateofthemap.org" do
+ aliases ["2008.stateofthemap.com", "2008.sotm.org"]
+ directory "/srv/2008.stateofthemap.org/wp"
+ database_name "sotm2008"
+ database_user "sotm2008"
+ database_password passwords["sotm2008"]
+ database_prefix "wp_sotm08_"
+ wp2fa_encrypt_key wp2fa_encrypt_keys["sotm2008"]
+ fpm_prometheus_port 12008
+end
+
+wordpress_theme "2008.stateofthemap.org-refreshwp-11" do
+ theme "refreshwp-11"
+ site "2008.stateofthemap.org"
+ repository "https://git.openstreetmap.org/public/stateofthemap.git"
+ revision "theme-2008"
+end
+
+# Remove broken geopress plugin
+wordpress_plugin "2008.stateofthemap.org-geopress" do
+ action :delete
+ plugin "geopress"
+ site "2008.stateofthemap.org"
+end
+
+directory "/srv/2009.stateofthemap.org" do
+ owner "wordpress"
+ group "wordpress"
+ mode "755"
+end
+
+git "/srv/2009.stateofthemap.org" do
+ action :sync
+ repository "https://git.openstreetmap.org/public/stateofthemap.git"
+ revision "resources-2009"
+ depth 1
+ user "wordpress"
+ group "wordpress"
+end
+
+wordpress_site "2009.stateofthemap.org" do
+ aliases ["2009.stateofthemap.com", "2009.sotm.org"]
+ directory "/srv/2009.stateofthemap.org/wp"
+ database_name "sotm2009"
+ database_user "sotm2009"
+ database_password passwords["sotm2009"]
+ wp2fa_encrypt_key wp2fa_encrypt_keys["sotm2009"]
+ urls "/register" => "/srv/2009.stateofthemap.org/register",
+ "/register-pro-user" => "/srv/2009.stateofthemap.org/register-pro-user",
+ "/podcasts" => "/srv/2009.stateofthemap.org/podcasts"
+ fpm_prometheus_port 12009
+end
+
+wordpress_theme "2009.stateofthemap.org-aerodrome" do
+ theme "aerodrome"
+ site "2009.stateofthemap.org"
+ repository "https://git.openstreetmap.org/public/stateofthemap.git"
+ revision "theme-2009"
+end
+
+# wordpress_plugin "2009.stateofthemap.org-wp-sticky" do
+# plugin "wp-sticky"
+# site "2009.stateofthemap.org"
+# end
+
+directory "/srv/2010.stateofthemap.org" do
+ owner "wordpress"
+ group "wordpress"
+ mode "755"
+end
+
+git "/srv/2010.stateofthemap.org" do
+ action :sync
+ repository "https://git.openstreetmap.org/public/stateofthemap.git"
+ revision "resources-2010"
+ depth 1
+ user "wordpress"
+ group "wordpress"
+end
+
+wordpress_site "2010.stateofthemap.org" do
+ aliases ["2010.stateofthemap.com", "2010.sotm.org"]
+ directory "/srv/2010.stateofthemap.org/wp"
+ database_name "sotm2010"
+ database_user "sotm2010"
+ database_password passwords["sotm2010"]
+ wp2fa_encrypt_key wp2fa_encrypt_keys["sotm2010"]
+ urls "/register" => "/srv/2010.stateofthemap.org/register"
+ fpm_prometheus_port 12010
+end
+
+wordpress_theme "2010.stateofthemap.org-aerodrome" do
+ theme "aerodrome"
+ site "2010.stateofthemap.org"
+ repository "https://git.openstreetmap.org/public/stateofthemap.git"
+ revision "theme-2010"
+end
+
+wordpress_plugin "2010.stateofthemap.org-sitepress-multilingual-cms" do
+ plugin "sitepress-multilingual-cms"
+ site "2010.stateofthemap.org"
+ repository "https://git.openstreetmap.org/private/sitepress-multilingual-cms.git"
+ revision "master"
+ not_if { kitchen? }
+end
+
+# wordpress_plugin "2010.stateofthemap.org-wp-sticky" do
+# plugin "wp-sticky"
+# site "2010.stateofthemap.org"
+# end
+
+directory "/srv/2011.stateofthemap.org" do
+ owner "wordpress"
+ group "wordpress"
+ mode "755"
+end
+
+git "/srv/2011.stateofthemap.org" do
+ action :sync
+ repository "https://git.openstreetmap.org/public/stateofthemap.git"
+ revision "resources-2011"
+ depth 1
+ user "wordpress"
+ group "wordpress"
+end
+
+wordpress_site "2011.stateofthemap.org" do
+ aliases ["2011.stateofthemap.com", "2011.sotm.org"]
+ directory "/srv/2011.stateofthemap.org/wp"
+ database_name "sotm2011"
+ database_user "sotm2011"
+ database_password passwords["sotm2011"]
+ wp2fa_encrypt_key wp2fa_encrypt_keys["sotm2011"]
+ urls "/register" => "/srv/2011.stateofthemap.org/register"
+ fpm_prometheus_port 12011
+end
+
+wordpress_theme "2011.stateofthemap.org-aerodrome" do
+ theme "aerodrome"
+ site "2011.stateofthemap.org"
+ repository "https://git.openstreetmap.org/public/stateofthemap.git"
+ revision "theme-2011"
+end
+
+wordpress_plugin "2011.stateofthemap.org-sitepress-multilingual-cms" do
+ plugin "sitepress-multilingual-cms"
+ site "2011.stateofthemap.org"
+ repository "https://git.openstreetmap.org/private/sitepress-multilingual-cms.git"
+ revision "master"
+ not_if { kitchen? }
+end
+
+# wordpress_plugin "2011.stateofthemap.org-wp-sticky" do
+# plugin "wp-sticky"
+# site "2011.stateofthemap.org"
+# end
+
+directory "/srv/2012.stateofthemap.org" do
+ owner "wordpress"
+ group "wordpress"
+ mode "755"
+end
+
+git "/srv/2012.stateofthemap.org" do
+ action :sync
+ repository "https://git.openstreetmap.org/public/stateofthemap.git"
+ revision "resources-2012"
+ depth 1
+ user "wordpress"
+ group "wordpress"
+end
+
+wordpress_site "2012.stateofthemap.org" do
+ aliases ["2012.stateofthemap.com", "2012.sotm.org"]
+ directory "/srv/2012.stateofthemap.org/wp"
+ database_name "sotm2012"
+ database_user "sotm2012"
+ database_password passwords["sotm2012"]
+ wp2fa_encrypt_key wp2fa_encrypt_keys["sotm2012"]
+ urls "/register" => "/srv/2012.stateofthemap.org/register"
+ fpm_prometheus_port 12012
+end
+
+wordpress_theme "2012.stateofthemap.org-aerodrome" do
+ theme "aerodrome"
+ site "2012.stateofthemap.org"
+ repository "https://git.openstreetmap.org/public/stateofthemap.git"
+ revision "theme-2012"
+end
+
+wordpress_plugin "2012.stateofthemap.org-leaflet-maps-marker" do
+ plugin "leaflet-maps-marker"
+ site "2012.stateofthemap.org"
+end
+
+wordpress_plugin "2012.stateofthemap.org-sitepress-multilingual-cms" do
+ plugin "sitepress-multilingual-cms"
+ site "2012.stateofthemap.org"
+ repository "https://git.openstreetmap.org/private/sitepress-multilingual-cms.git"
+ revision "master"
+ not_if { kitchen? }
+end
+
+# wordpress_plugin "2012.stateofthemap.org-wp-sticky" do
+# plugin "wp-sticky"
+# site "2012.stateofthemap.org"
+# end
+
+template "/etc/cron.daily/sotm-backup" do
+ source "backup.cron.erb"
+ owner "root"
+ group "root"
+ mode "750"
+ variables :passwords => passwords
+end
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-<VirtualHost *:80>
- ServerName stateofthemap.org
- ServerAlias stateofthemap.com
- ServerAlias sotm.org
- ServerAlias www.stateofthemap.org
- ServerAlias www.stateofthemap.com
- ServerAlias www.sotm.org
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/stateofthemap.org-access.log combined
- ErrorLog /var/log/apache2/stateofthemap.org-error.log
-
- RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
- RedirectPermanent / https://stateofthemap.org/
-</VirtualHost>
-
-<VirtualHost *:443>
- ServerName stateofthemap.com
- ServerAlias sotm.org
- ServerAlias www.stateofthemap.org
- ServerAlias www.stateofthemap.com
- ServerAlias www.sotm.org
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/stateofthemap.org-access.log combined
- ErrorLog /var/log/apache2/stateofthemap.org-error.log
-
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/stateofthemap.org.pem
- SSLCertificateKeyFile /etc/ssl/private/stateofthemap.org.key
-
- RedirectPermanent / https://stateofthemap.org/
-</VirtualHost>
-
-<VirtualHost *:443>
- ServerName stateofthemap.org
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/stateofthemap.org-access.log combined
- ErrorLog /var/log/apache2/stateofthemap.org-error.log
-
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/stateofthemap.org.pem
- SSLCertificateKeyFile /etc/ssl/private/stateofthemap.org.key
-
- DocumentRoot /srv/stateofthemap.org/html
-
- ErrorDocument 404 /404.html
-
- ExpiresActive On
- ExpiresDefault "access plus 12 hours"
-</VirtualHost>
-
-<Directory /srv/stateofthemap.org/html>
- Require all granted
-</Directory>
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-<VirtualHost *:80>
- ServerName <%= @year %>.stateofthemap.org
- ServerAlias <%= @year %>.stateofthemap.com <%= @year %>.sotm.org
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/<%= @year %>.stateofthemap.org-access.log combined
- ErrorLog /var/log/apache2/<%= @year %>.stateofthemap.org-error.log
-
- RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
- RedirectPermanent / https://<%= @year %>.stateofthemap.org/
-</VirtualHost>
-
-<VirtualHost *:443>
- ServerName <%= @year %>.stateofthemap.com
- ServerAlias <%= @year %>.sotm.org
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/<%= @year %>.stateofthemap.org-access.log combined
- ErrorLog /var/log/apache2/<%= @year %>.stateofthemap.org-error.log
-
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/<%= @year %>.stateofthemap.org.pem
- SSLCertificateKeyFile /etc/ssl/private/<%= @year %>.stateofthemap.org.key
-
- RedirectPermanent / https://<%= @year %>.stateofthemap.org/
-</VirtualHost>
-
-<VirtualHost *:443>
- ServerName <%= @year %>.stateofthemap.org
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/<%= @year %>.stateofthemap.org-access.log combined
- ErrorLog /var/log/apache2/<%= @year %>.stateofthemap.org-error.log
-
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/<%= @year %>.stateofthemap.org.pem
- SSLCertificateKeyFile /etc/ssl/private/<%= @year %>.stateofthemap.org.key
-
- DocumentRoot /srv/<%= @year %>.stateofthemap.org/_site
-
- ErrorDocument 404 /404.html
-
- ExpiresActive On
- ExpiresDefault "access plus 10 minutes"
-</VirtualHost>
-
-<Directory /srv/<%= @year %>.stateofthemap.org/_site>
- Require all granted
-</Directory>
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-<VirtualHost *:80>
- ServerName <%= @year %>.stateofthemap.org
- ServerAlias <%= @year %>.stateofthemap.com <%= @year %>.sotm.org
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/<%= @year %>.stateofthemap.org-access.log combined
- ErrorLog /var/log/apache2/<%= @year %>.stateofthemap.org-error.log
-
- RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
- RedirectPermanent / https://<%= @year %>.stateofthemap.org/
-</VirtualHost>
-
-<VirtualHost *:443>
- ServerName <%= @year %>.stateofthemap.com
- ServerAlias <%= @year %>.sotm.org
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/<%= @year %>.stateofthemap.org-access.log combined
- ErrorLog /var/log/apache2/<%= @year %>.stateofthemap.org-error.log
-
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/<%= @year %>.stateofthemap.org.pem
- SSLCertificateKeyFile /etc/ssl/private/<%= @year %>.stateofthemap.org.key
-
- RedirectPermanent / https://<%= @year %>.stateofthemap.org/
-</VirtualHost>
-
-<VirtualHost *:443>
- ServerName <%= @year %>.stateofthemap.org
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/<%= @year %>.stateofthemap.org-access.log combined
- ErrorLog /var/log/apache2/<%= @year %>.stateofthemap.org-error.log
-
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/<%= @year %>.stateofthemap.org.pem
- SSLCertificateKeyFile /etc/ssl/private/<%= @year %>.stateofthemap.org.key
-
- DocumentRoot /srv/<%= @year %>.stateofthemap.org
-
- ErrorDocument 404 /404.html
-
- ExpiresActive On
- ExpiresDefault "access plus 7 days"
-</VirtualHost>
-
-<Directory /srv/<%= @year %>.stateofthemap.org>
- Require all granted
-</Directory>
mkdir $T/sotm-$D
-<% %w(2007 2008 2009 2010 2011 2012 2016).each do |year| -%>
+<% %w(2007 2008 2009 2010 2011 2012).each do |year| -%>
echo '[mysqldump]' > $T/mysqldump.opts
echo 'user=sotm<%= year %>' >> $T/mysqldump.opts
echo 'password=<%= @passwords["sotm#{year}"] %>' >> $T/mysqldump.opts
ln -s /srv/2010.stateofthemap.org $T/sotm-$D/www2010
ln -s /srv/2011.stateofthemap.org $T/sotm-$D/www2011
ln -s /srv/2012.stateofthemap.org $T/sotm-$D/www2012
-ln -s /srv/2016.stateofthemap.org $T/sotm-$D/www2016
export RSYNC_RSH="ssh -ax"
+++ /dev/null
-#!/bin/sh
-
-/usr/bin/sudo -u trac /usr/bin/trac-admin /var/lib/trac changeset added "$1" "$2"
+++ /dev/null
-#!/bin/sh
-
-/usr/bin/sudo -u trac /usr/bin/trac-admin /var/lib/trac changeset modified "$1" "$2"
version "1.0.0"
supports "ubuntu"
-depends "apache"
+depends "podman"
# limitations under the License.
#
-include_recipe "apache"
+include_recipe "podman::apache"
-package "subversion"
-
-repository_directory = "/var/lib/subversion/repos/openstreetmap"
-
-remote_directory "#{repository_directory}/hooks" do
- source "hooks"
- owner "www-data"
- group "www-data"
- mode "755"
- files_owner "www-data"
- files_group "www-data"
- files_mode "755"
- purge false
-end
-
-apache_module "dav" do
- package "apache2"
-end
-
-apache_module "dav_fs" do
- package "apache2"
-end
-
-apache_module "dav_svn" do
- package "libapache2-mod-svn"
-end
-
-apache_module "authz_svn" do
- package "libapache2-mod-svn"
-end
-
-ssl_certificate "svn.openstreetmap.org" do
- domains ["svn.openstreetmap.org", "svn.osm.org"]
- notifies :reload, "service[apache2]"
-end
-
-apache_site "svn.openstreetmap.org" do
- template "apache.erb"
- directory repository_directory
- variables :realm => "Subversion Repository", :password_file => "/etc/apache2/svn.passwd", :aliases => ["svn.osm.org"]
-end
-
-template "/etc/cron.daily/svn-backup" do
- source "backup.cron.erb"
- owner "root"
- group "root"
- mode "755"
+podman_site "svn.openstreetmap.org" do
+ image "ghcr.io/openstreetmap/svn-website:latest"
+ aliases ["svn.osm.org"]
end
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-<VirtualHost *:443>
- ServerName <%= @name %>
- ServerAdmin webmaster@openstreetmap.org
-
- Protocols http/1.1
-
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
- SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
-
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
- CustomLog /var/log/apache2/<%= @name %>-svn-access.log "%h %t %u %{SVN-ACTION}e" env=SVN-ACTION
- ErrorLog /var/log/apache2/<%= @name %>-error.log
-
- <Location />
- DAV svn
- SVNPath <%= @directory %>
- SVNIndexXSLT /svnindex.xsl
-
- LimitXMLRequestBody 0
- LimitRequestBody 0
-
- <Limit GET PROPFIND OPTIONS REPORT>
- Require all granted
- </Limit>
-
- <LimitExcept GET PROPFIND OPTIONS REPORT>
- Require all denied
- </LimitExcept>
- </Location>
-</VirtualHost>
-<% unless @aliases.empty? -%>
-
-<VirtualHost *:443>
- ServerName <%= @aliases.first %>
-<% @aliases.drop(1).each do |alias_name| -%>
- ServerAlias <%= alias_name %>
-<% end -%>
- ServerAdmin webmaster@openstreetmap.org
-
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
- SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
-
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
- ErrorLog /var/log/apache2/<%= @name %>-error.log
-
- RedirectPermanent / https://<%= @name %>/
-</VirtualHost>
-<% end -%>
-
-<VirtualHost *:80>
- ServerName <%= @name %>
-<% @aliases.each do |alias_name| -%>
- ServerAlias <%= alias_name %>
-<% end -%>
-
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
- ErrorLog /var/log/apache2/<%= @name %>-error.log
-
- RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
- RedirectPermanent / https://<%= @name %>/
-</VirtualHost>
+++ /dev/null
-#!/bin/sh
-
-# DO NOT EDIT - This file is being maintained by Chef
-
-T=$(mktemp -d -t -p /var/tmp svn.XXXXXXXXXX)
-D=$(date +%Y-%m-%d)
-B=svn-$D.tar.gz
-
-nice svnadmin hotcopy /var/lib/subversion/repos/openstreetmap $T/svn-$D > /dev/null
-
-export RSYNC_RSH="ssh -ax"
-
-nice tar --create --directory=$T svn-$D | nice gzip --rsyncable -9 > $T/$B
-nice rsync --preallocate --fuzzy $T/$B backup::backup
-
-rm -rf $T
after "network.target"
user "supybot"
exec_start "/usr/bin/supybot /etc/supybot/supybot.conf"
- private_tmp true
- private_devices true
- protect_system true
- protect_home true
- no_new_privileges true
+ sandbox :enable_network => true
+ read_write_paths ["/etc/supybot", "/var/lib/supybot", "/var/log/supybot"]
restart "on-failure"
end
-channel #osm-dev-test
+channel #osm-dev
lobotomized False
defaultAllow True
- capability -halfop
capability -protected
capability -op
capability -voice
+ capability -halfop
-channel #osm-dev
+channel #osm-dev-test
lobotomized False
defaultAllow True
- capability -halfop
capability -protected
capability -op
capability -voice
+ capability -halfop
[osm-cgimap]
short name = osm-cgimap
-url = https://git.openstreetmap.org/public/cgimap.git
+url = https://github.com/zerebubuth/openstreetmap-cgimap.git
branch = master
-commit link = https://github.com/openstreetmap/cgimap/commit/%c
+commit link = https://github.com/zerebubuth/openstreetmap-cgimap/commit/%c
channels = #osm-dev
commit message = [%s|%b|%a] %m %l
channels = #osm-dev
commit message = [%s|%b|%a] %m %l
-[osm-potlatch2]
-short name = osm-potlatch2
-url = https://git.openstreetmap.org/public/potlatch2.git
-branch = master
-commit link = https://github.com/openstreetmap/potlatch2/commit/%c
-channels = #osm-dev
-commit message = [%s|%b|%a] %m %l
-
-[osm-gpx-import]
-short name = osm-gpx-import
-url = https://git.openstreetmap.org/public/gpx-import.git
-branch = master
-commit link = https://git.osm.org/gpx-import.git/commitdiff/%c
-channels = #osm-dev
-commit message = [%s|%b|%a] %m %l
-
[osm-nominatim]
short name = osm-nominatim
url = https://git.openstreetmap.org/public/nominatim.git
channels = #osm-dev
commit message = [%s|%b|%a] %m %l
-[osm-planetdump]
-short name = osm-planetdump
-url = https://git.openstreetmap.org/public/planetdump.git
+[osm-planetdump-ng]
+short name = osm-planetdump-ng
+url = https://github.com/zerebubuth/planet-dump-ng.git
branch = master
-commit link = https://git.osm.org/planetdump.git/commitdiff/%c
+commit link = https://github.com/zerebubuth/planet-dump-ng-commit/%c
channels = #osm-dev
commit message = [%s|%b|%a] %m %l
channels = #osm-dev
commit message = [%s|%b|%a] %m %l
-[osm-osm2pgsql-0.92.x]
-short name = osm-osm2pgsql-0.92.x
-url = https://github.com/openstreetmap/osm2pgsql.git
-branch = 0.92.x
-commit link = https://github.com/openstreetmap/osm2pgsql/commit/%c
-channels = #osm-dev
-commit message = [%s|%b|%a] %m %l
-
-[osm-osm2pgsql-0.90.x]
-short name = osm-osm2pgsql-0.90.x
-url = https://github.com/openstreetmap/osm2pgsql.git
-branch = 0.90.x
-commit link = https://github.com/openstreetmap/osm2pgsql/commit/%c
-channels = #osm-dev
-commit message = [%s|%b|%a] %m %l
-
-[osm-osm2pgsql-0.88.x]
-short name = osm-osm2pgsql-0.88.x
-url = https://github.com/openstreetmap/osm2pgsql.git
-branch = 0.88.x
-commit link = https://github.com/openstreetmap/osm2pgsql/commit/%c
-channels = #osm-dev
-commit message = [%s|%b|%a] %m %l
-
[osm-mod_tile]
short name = osm-mod_tile
url = https://github.com/openstreetmap/mod_tile.git
[osm-id]
short name = osm-id
url = https://github.com/openstreetmap/iD.git
-branch = master
+branch = develop
commit link = https://github.com/openstreetmap/iD/commit/%c
channels = #osm-dev
commit message = [%s|%b|%a] %m %l
[osmf-server-info]
short name = osmf-server-info
-url = https://github.com/gravitystorm/osmf-server-info.git
+url = https://github.com/osmfoundation/osmf-server-info.git
branch = master
-commit link = https://github.com/gravitystorm/osmf-server-info/commit/%c
-channels = #osm-dev
-commit message = [%s|%b|%a] %m %l
-
-[osm-forum]
-short name = osm-forum
-url = https://github.com/openstreetmap/openstreetmap-forum.git
-branch = openstreetmap-1.5.10
-commit link = https://github.com/openstreetmap/openstreetmap-forum/commit/%c
+commit link = https://github.com/osmfoundation/osmf-server-info/commit/%c
channels = #osm-dev
commit message = [%s|%b|%a] %m %l
channels = #osm-dev
commit message = [%s|%b|%a] %m %l
+[osm-tilelog]
+short name = osm-tilelog
+url = https://github.com/openstreetmap/tilelog.git
+branch = main
+commit link = https://github.com/openstreetmap/tilelog/commit/%c
+channels = #osm-dev
+commit message = [%s|%b|%a] %m %l
+
[osm-josm]
short name = osm-josm
-url = https://github.com/openstreetmap/josm.git
+url = https://github.com/JOSM/josm.git
branch = master
-commit link = https://github.com/openstreetmap/josm/commit/%c
+commit link = https://github.com/JOSM/josm/commit/%c
channels = #osm-dev
commit message = [%s|%b|%a] %m %l
[osmlab-osm-community-index]
short name = osmlab-osm-community-index
url = https://github.com/osmlab/osm-community-index.git
-branch = master
+branch = main
commit link = https://github.com/osmlab/osm-community-index/commit/%c
channels = #osm-dev
commit message = [%s|%b|%a] %m %l
short name = vespucci
url = https://github.com/MarcusWolschon/osmeditor4android.git
branch = master
-commit link = https://github.com//MarcusWolschon/osmeditor4android/commit/%c
+commit link = https://github.com/MarcusWolschon/osmeditor4android/commit/%c
channels = #osm-dev
commit message = [%s|%b|%a] %m %l
version "1.0.0"
supports "ubuntu"
-depends "apache"
-depends "git"
+depends "podman"
# limitations under the License.
#
-include_recipe "apache"
-include_recipe "git"
+include_recipe "podman::apache"
-package %w[
- gcc
- g++
- make
- ruby
- ruby-dev
- libssl-dev
- zlib1g-dev
- pkg-config
-]
-
-apache_module "expires"
-apache_module "rewrite"
-
-gem_package "bundler" do
- version "1.17.3"
-end
-
-git "/srv/switch2osm.org" do
- action :sync
- repository "https://github.com/switch2osm/switch2osm.github.io.git"
- depth 1
- user "root"
- group "root"
- notifies :run, "execute[/srv/switch2osm.org/Gemfile]"
-end
-
-directory "/srv/switch2osm.org/_site" do
- mode "755"
- owner "nobody"
- group "nogroup"
-end
-
-# Workaround https://github.com/jekyll/jekyll/issues/7804
-# by creating a .jekyll-cache folder
-directory "/srv/switch2osm.org/.jekyll-cache" do
- mode "755"
- owner "nobody"
- group "nogroup"
-end
-
-execute "/srv/switch2osm.org/Gemfile" do
- action :nothing
- command "bundle install --deployment"
- cwd "/srv/switch2osm.org"
- user "root"
- group "root"
- notifies :run, "execute[/srv/switch2osm.org]"
-end
-
-execute "/srv/switch2osm.org" do
- action :nothing
- command "bundle exec jekyll build --trace --config _config.yml,_config_osm.yml"
- cwd "/srv/switch2osm.org"
- user "nobody"
- group "nogroup"
-end
-
-ssl_certificate "switch2osm.org" do
- domains ["switch2osm.org",
- "www.switch2osm.org", "switch2osm.com", "www.switch2osm.com"]
- notifies :reload, "service[apache2]"
-end
-
-apache_site "switch2osm.org" do
- template "apache.erb"
- directory "/srv/switch2osm.org/_site"
+podman_site "switch2osm.org" do
+ image "ghcr.io/switch2osm/switch2osm:latest"
+ aliases ["www.switch2osm.org", "switch2osm.com", "www.switch2osm.com"]
end
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-<VirtualHost *:443>
- ServerName <%= @name %>
- ServerAlias www.switch2osm.org
- ServerAlias switch2osm.com
- ServerAlias www.switch2osm.com
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
- ErrorLog /var/log/apache2/<%= @name %>-error.log
-
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
- SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
-
- DocumentRoot <%= @directory %>
-
- ErrorDocument 404 /404.html
-
- ExpiresActive On
- ExpiresDefault "access plus 10 minutes"
-</VirtualHost>
-
-<VirtualHost *:80>
- ServerName <%= @name %>
- ServerAlias www.switch2osm.org
- ServerAlias switch2osm.com
- ServerAlias www.switch2osm.com
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
- ErrorLog /var/log/apache2/<%= @name %>-error.log
-
- RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
- RedirectPermanent / https://<%= @name %>/
-</VirtualHost>
-
-<Directory <%= @directory %>>
- Require all granted
-</Directory>
property :after, [String, Array]
property :conflicts, [String, Array]
property :wants, [String, Array]
+property :requires, [String, Array]
+property :joins_namespace_of, [String, Array]
property :type, String, :is => %w[simple forking oneshot dbus notify idle]
+property :notify_access, String, :is => %w[none main exec all]
property :limit_nofile, Integer
property :limit_as, [Integer, String]
property :limit_cpu, [Integer, String]
property :environment_file, [String, Hash]
property :user, String
property :group, String
+property :dynamic_user, [true, false]
property :working_directory, String
-property :exec_start_pre, String
-property :exec_start, String
-property :exec_start_post, String
-property :exec_stop, String
+property :umask, String
+property :exec_start_pre, [String, Array]
+property :exec_start, [String, Array]
+property :exec_start_post, [String, Array]
+property :exec_stop, [String, Array]
+property :exec_stop_post, [String, Array]
property :exec_reload, String
+property :runtime_max_sec, Integer
property :runtime_directory, String
property :runtime_directory_mode, Integer
+property :state_directory, String
+property :state_directory_mode, Integer
+property :cache_directory, String
+property :cache_directory_mode, Integer
+property :logs_directory, String
+property :logs_directory_mode, Integer
+property :configuration_directory, String
+property :configuration_directory_mode, Integer
property :standard_input, String,
:is => %w[null tty tty-force tty-fail socket]
property :standard_output, String,
property :success_exit_status, [Integer, String, Array]
property :restart, String,
:is => %w[on-success on-failure on-abnormal on-watchdog on-abort always]
-property :private_tmp, [true, false]
-property :private_devices, [true, false]
-property :private_network, [true, false]
-property :protect_system, [TrueClass, FalseClass, String]
-property :protect_home, [TrueClass, FalseClass, String]
+property :restart_sec, [Integer, String]
+property :protect_proc, String,
+ :is => %w[noaccess invisible ptraceable default]
+property :proc_subset, String,
+ :is => %w[all pid]
+property :bind_paths, [String, Array]
+property :bind_read_only_paths, [String, Array]
+property :capability_bounding_set, [String, Array]
+property :ambient_capabilities, [String, Array]
+property :no_new_privileges, [true, false]
+property :protect_system, [true, false, String]
+property :protect_home, [true, false, String]
property :read_write_paths, [String, Array]
property :read_only_paths, [String, Array]
property :inaccessible_paths, [String, Array]
+property :private_tmp, [true, false]
+property :private_devices, [true, false]
+property :private_network, [true, false]
+property :private_ipc, [true, false]
+property :private_users, [true, false]
+property :protect_hostname, [true, false]
+property :protect_clock, [true, false]
+property :protect_kernel_tunables, [true, false]
+property :protect_kernel_modules, [true, false]
+property :protect_kernel_logs, [true, false]
+property :protect_control_groups, [true, false]
property :restrict_address_families, [String, Array]
-property :no_new_privileges, [true, false]
+property :restrict_namespaces, [true, false, String, Array]
+property :lock_personality, [true, false]
+property :memory_deny_write_execute, [true, false]
+property :restrict_realtime, [true, false]
+property :restrict_suid_sgid, [true, false]
+property :remove_ipc, [true, false]
+property :system_call_filter, [String, Array]
+property :system_call_architectures, [String, Array]
property :tasks_max, Integer
+property :timeout_start_sec, Integer
+property :timeout_stop_sec, Integer
+property :timeout_abort_sec, Integer
property :timeout_sec, Integer
property :pid_file, String
property :nice, Integer
property :io_scheduling_priority, Integer
property :kill_mode, String,
:is => %w[control-group process mixed none]
+property :sandbox, [true, false, Hash]
action :create do
service_variables = new_resource.to_hash
service_variables[:type] ||= "simple"
end
+ if new_resource.sandbox
+ service_variables[:protect_proc] = "invisible" unless property_is_set?(:protect_proc)
+ service_variables[:proc_subset] = "pid" unless property_is_set?(:proc_subset)
+ service_variables[:capability_bounding_set] = [] unless property_is_set?(:capability_bounding_set)
+ service_variables[:ambient_capabilities] = [] unless property_is_set?(:ambient_capabilities)
+ service_variables[:no_new_privileges] = true unless property_is_set?(:no_new_privileges)
+ service_variables[:protect_system] = "strict" unless property_is_set?(:protect_system)
+ service_variables[:protect_home] = true unless property_is_set?(:protect_home)
+ service_variables[:private_tmp] = true unless property_is_set?(:private_tmp)
+ service_variables[:private_devices] = true unless property_is_set?(:private_devices)
+ service_variables[:private_network] = true unless property_is_set?(:private_network)
+ service_variables[:private_ipc] = true unless property_is_set?(:private_ipc)
+ service_variables[:private_users] = true unless property_is_set?(:private_users)
+ service_variables[:protect_hostname] = true unless property_is_set?(:protect_hostname)
+ service_variables[:protect_clock] = true unless property_is_set?(:protect_clock)
+ service_variables[:protect_kernel_tunables] = true unless property_is_set?(:protect_kernel_tunables)
+ service_variables[:protect_kernel_modules] = true unless property_is_set?(:protect_kernel_modules)
+ service_variables[:protect_kernel_logs] = true unless property_is_set?(:protect_kernel_logs)
+ service_variables[:protect_control_groups] = true unless property_is_set?(:protect_control_groups)
+ service_variables[:restrict_address_families] = [] unless property_is_set?(:restrict_address_families)
+ service_variables[:restrict_namespaces] = true unless property_is_set?(:restrict_namespaces)
+ service_variables[:lock_personality] = true unless property_is_set?(:lock_personality)
+ service_variables[:memory_deny_write_execute] = true unless property_is_set?(:memory_deny_write_execute)
+ service_variables[:restrict_realtime] = true unless property_is_set?(:restrict_realtime)
+ service_variables[:restrict_suid_sgid] = true unless property_is_set?(:restrict_suid_sgid)
+ service_variables[:remove_ipc] = true unless property_is_set?(:remove_ipc)
+ service_variables[:system_call_filter] = "@system-service" unless property_is_set?(:system_call_filter)
+ service_variables[:system_call_architectures] = "native" unless property_is_set?(:system_call_architectures)
+
+ if sandbox_option(:enable_network)
+ service_variables[:private_network] = false
+ service_variables[:restrict_address_families] = Array(service_variables[:restrict_address_families]).append("AF_INET", "AF_INET6").reject { |f| f == "none" }
+ end
+ end
+
if new_resource.environment_file.is_a?(Hash)
template "/etc/default/#{new_resource.service}" do
cookbook "systemd"
end
action_class do
+ def sandbox_option(option)
+ new_resource.sandbox[option] if new_resource.sandbox.is_a?(Hash)
+ end
+
def dropin_directory
"/etc/systemd/system/#{new_resource.service}.service.d"
end
--- /dev/null
+#
+# Cookbook:: systemd
+# Resource:: systemd_socket
+#
+# Copyright:: 2021, OpenStreetMap Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+unified_mode true
+
+default_action :create
+
+property :socket, String, :name_property => true
+property :description, String, :required => [:create]
+property :after, [String, Array]
+property :wants, [String, Array]
+property :listen_stream, [String, Array]
+property :listen_datagram, [String, Array]
+property :listen_sequential_packet, [String, Array]
+property :listen_fifo, [String, Array]
+property :listen_special, [String, Array]
+property :listen_netlink, [String, Array]
+property :listen_message_queue, [String, Array]
+property :listen_usb_function, [String, Array]
+property :socket_protocol, String
+property :bind_ipv6_only, String
+property :backlog, Integer
+property :bind_to_device, String
+property :socket_user, String
+property :socket_group, String
+property :socket_mode, Integer
+property :directory_mode, Integer
+property :accept, [true, false]
+property :writable, [true, false]
+property :max_connections, Integer
+property :max_connections_per_source, Integer
+property :keep_alive, [true, false]
+property :keep_alive_time_sec, Integer
+property :keep_alive_interval_sec, Integer
+property :keep_alive_probes, Integer
+property :no_delay, [true, false]
+property :priority, Integer
+property :defer_accept_sec, Integer
+property :receive_buffer, Integer
+property :send_buffer, Integer
+property :ip_tos, Integer
+property :ip_ttl, Integer
+property :mark, Integer
+property :reuse_port, [true, false]
+property :pipe_size, Integer
+property :message_queue_max_messages, Integer
+property :message_queue_message_size, Integer
+property :free_bind, [true, false]
+property :transparent, [true, false]
+property :broadcast, [true, false]
+property :pass_credentials, [true, false]
+property :pass_security, [true, false]
+property :tcp_congestion, String
+property :exec_start_pre, [String, Array]
+property :exec_start, [String, Array]
+property :exec_start_post, [String, Array]
+property :exec_stop, [String, Array]
+property :timeout_sec, [Integer, String]
+property :service, String
+property :remove_on_stop, [true, false]
+property :symlinks, [String, Array]
+property :file_descriptor_name, String
+property :trigger_limit_interval_sec, [Integer, String]
+property :trigger_limit_burst, Integer
+
+action :create do
+ socket_variables = new_resource.to_hash
+
+ template "/etc/systemd/system/#{new_resource.socket}.socket" do
+ cookbook "systemd"
+ source "socket.erb"
+ owner "root"
+ group "root"
+ mode "644"
+ variables socket_variables
+ end
+
+ execute "systemctl-reload-#{new_resource.socket}.socket" do
+ action :nothing
+ command "systemctl daemon-reload"
+ user "root"
+ group "root"
+ subscribes :run, "template[/etc/systemd/system/#{new_resource.socket}.socket]"
+ end
+end
+
+action :delete do
+ file "/etc/systemd/system/#{new_resource.socket}.socket" do
+ action :delete
+ end
+
+ execute "systemctl-reload-#{new_resource.socket}.socket" do
+ action :nothing
+ command "systemctl daemon-reload"
+ user "root"
+ group "root"
+ subscribes :run, "file[/etc/systemd/system/#{new_resource.socket}.socket]"
+ end
+end
default_action :create
property :timer, String, :name_property => true
-property :description, String, :required => [:create]
+property :dropin, String
+property :description, String
property :after, [String, Array]
property :wants, [String, Array]
property :on_active_sec, [Integer, String]
action :create do
timer_variables = new_resource.to_hash
- template "/etc/systemd/system/#{new_resource.timer}.timer" do
+ if new_resource.dropin
+ directory dropin_directory do
+ owner "root"
+ group "root"
+ mode "755"
+ end
+ end
+
+ template config_name do
cookbook "systemd"
source "timer.erb"
owner "root"
group "root"
mode "644"
variables timer_variables
+ notifies :run, "execute[systemctl-reload]"
end
- execute "systemctl-reload-#{new_resource.timer}.timer" do
+ execute "systemctl-reload" do
action :nothing
command "systemctl daemon-reload"
user "root"
group "root"
- subscribes :run, "template[/etc/systemd/system/#{new_resource.timer}.timer]"
end
end
action :delete do
- file "/etc/systemd/system/#{new_resource.timer}.timer" do
+ file config_name do
action :delete
end
subscribes :run, "file[/etc/systemd/system/#{new_resource.timer}.timer]"
end
end
+
+action_class do
+ def dropin_directory
+ "/etc/systemd/system/#{new_resource.timer}.timer.d"
+ end
+
+ def config_name
+ if new_resource.dropin
+ "#{dropin_directory}/#{new_resource.dropin}.conf"
+ else
+ "/etc/systemd/system/#{new_resource.timer}.timer"
+ end
+ end
+end
<% if @wants -%>
Wants=<%= Array(@wants).join(" ") %>
<% end -%>
+<% if @requires -%>
+Requires=<%= Array(@requires).join(" ") %>
+<% end -%>
+<% if @joins_namespace_of -%>
+JoinsNamespaceOf=<%= Array(@joins_namespace_of).join(" ") %>
+<% end -%>
[Service]
<% if @type -%>
Type=<%= @type %>
<% end -%>
+<% if @notify_access -%>
+NotifyAccess=<%= @notify_access %>
+<% end -%>
<% if @limit_nofile -%>
LimitNOFILE=<%= @limit_nofile %>
<% end -%>
<% if @group -%>
Group=<%= @group %>
<% end -%>
+<% if @dynamic_user -%>
+DynamicUser=<%= @dynamic_user %>
+<% end -%>
<% if @working_directory -%>
WorkingDirectory=<%= @working_directory %>
<% end -%>
+<% if @umask -%>
+UMask=<%= @umask %>
+<% end -%>
<% if @exec_start_pre -%>
<% if @dropin -%>
ExecStartPre=
<% end -%>
-ExecStartPre=<%= @exec_start_pre %>
+<% Array(@exec_start_pre).each do |exec_start_pre| -%>
+ExecStartPre=<%= exec_start_pre %>
+<% end -%>
<% end -%>
<% if @exec_start -%>
<% if @dropin -%>
ExecStart=
<% end -%>
-ExecStart=<%= @exec_start %>
+<% Array(@exec_start).each do |exec_start| -%>
+ExecStart=<%= exec_start %>
+<% end -%>
<% end -%>
<% if @exec_start_post -%>
<% if @dropin -%>
ExecStartPost=
<% end -%>
-ExecStartPost=<%= @exec_start_post %>
+<% Array(@exec_start_post).each do |exec_start_post| -%>
+ExecStartPost=<%= exec_start_post %>
+<% end -%>
<% end -%>
<% if @exec_stop -%>
<% if @dropin -%>
ExecStop=
<% end -%>
-ExecStop=<%= @exec_stop %>
+<% Array(@exec_stop).each do |exec_stop| -%>
+ExecStop=<%= exec_stop %>
+<% end -%>
+<% end -%>
+<% if @exec_stop_post -%>
+<% if @dropin -%>
+ExecStopPost=
+<% end -%>
+<% Array(@exec_stop_post).each do |exec_stop_post| -%>
+ExecStopPost=<%= exec_stop_post %>
+<% end -%>
<% end -%>
<% if @exec_reload -%>
<% if @dropin -%>
<% end -%>
ExecReload=<%= @exec_reload %>
<% end -%>
+<% if @runtime_max_sec -%>
+RuntimeMaxSec=<%= @runtime_max_sec %>
+<% end -%>
<% if @runtime_directory -%>
RuntimeDirectory=<%= @runtime_directory %>
<% end -%>
<% if @runtime_directory_mode -%>
RuntimeDirectoryMode=<%= sprintf("0%o", @runtime_directory_mode) %>
<% end -%>
+<% if @state_directory -%>
+StateDirectory=<%= @state_directory %>
+<% end -%>
+<% if @state_directory_mode -%>
+StateDirectoryMode=<%= sprintf("0%o", @state_directory_mode) %>
+<% end -%>
+<% if @cache_directory -%>
+CacheDirectory=<%= @cache_directory %>
+<% end -%>
+<% if @cache_directory_mode -%>
+CacheDirectoryMode=<%= sprintf("0%o", @cache_directory_mode) %>
+<% end -%>
+<% if @logs_directory -%>
+LogsDirectory=<%= @logs_directory %>
+<% end -%>
+<% if @logs_directory_mode -%>
+LogsDirectoryMode=<%= sprintf("0%o", @logs_directory_mode) %>
+<% end -%>
+<% if @configuration_directory -%>
+ConfigurationDirectory=<%= @configuration_directory %>
+<% end -%>
+<% if @configuration_directory_mode -%>
+ConfigurationDirectoryMode=<%= sprintf("0%o", @configuration_directory_mode) %>
+<% end -%>
<% if @standard_input -%>
StandardInput=<%= @standard_input %>
<% end -%>
<% if @standard_error -%>
StandardError=<%= @standard_error %>
<% end -%>
-<% if @private_tmp -%>
-PrivateTmp=<%= @private_tmp %>
+<% if @protect_proc && node[:lsb][:release].to_f >= 22.04 -%>
+ProtectProc=<%= @protect_proc %>
<% end -%>
-<% if @private_devices -%>
-PrivateDevices=<%= @private_devices %>
+<% if @proc_subset && node[:lsb][:release].to_f >= 22.04 -%>
+ProcSubset=<%= @proc_subset %>
<% end -%>
-<% if @private_network -%>
-PrivateNetwork=<%= @private_network %>
+<% if @bind_paths -%>
+BindPaths=<%= Array(@bind_paths).sort.uniq.join(" ") %>
+<% end -%>
+<% if @bind_read_only_paths -%>
+BindReadOnlyPaths=<%= Array(@bind_read_only_paths).sort.uniq.join(" ") %>
+<% end -%>
+<% if @no_new_privileges -%>
+NoNewPrivileges=<%= @no_new_privileges %>
+<% end -%>
+<% if @capability_bounding_set -%>
+CapabilityBoundingSet=<%= Array(@capability_bounding_set).sort.uniq.join(" ") %>
+<% end -%>
+<% if @ambient_capabilities -%>
+AmbientCapabilities=<%= Array(@ambient_capabilities).sort.uniq.join(" ") %>
<% end -%>
<% if @protect_system -%>
ProtectSystem=<%= @protect_system %>
ProtectHome=<%= @protect_home %>
<% end -%>
<% if @read_write_paths -%>
-ReadWritePaths=<%= Array(@read_write_paths).join(" ") %>
+ReadWritePaths=<%= Array(@read_write_paths).sort.uniq.join(" ") %>
<% end -%>
<% if @read_only_paths -%>
-ReadOnlyPaths=<%= Array(@read_only_paths).join(" ") %>
+ReadOnlyPaths=<%= Array(@read_only_paths).sort.uniq.join(" ") %>
<% end -%>
<% if @inaccessible_paths -%>
-InaccessiblePaths=<%= Array(@inaccessible_paths).join(" ") %>
+InaccessiblePaths=<%= Array(@inaccessible_paths).sort.uniq.join(" ") %>
+<% end -%>
+<% if @private_tmp -%>
+PrivateTmp=<%= @private_tmp %>
+<% end -%>
+<% if @private_devices -%>
+PrivateDevices=<%= @private_devices %>
+<% end -%>
+<% if @private_network -%>
+PrivateNetwork=<%= @private_network %>
+<% end -%>
+<% if @private_ipc && node[:lsb][:release].to_f >= 22.04 -%>
+PrivateIPC=<%= @private_ipc %>
+<% end -%>
+<% if @private_users -%>
+PrivateUsers=<%= @private_users %>
+<% end -%>
+<% if @protect_hostname -%>
+ProtectHostname=<%= @protect_hostname %>
+<% end -%>
+<% if @protect_clock -%>
+ProtectClock=<%= @protect_clock %>
+<% end -%>
+<% if @protect_kernel_tunables -%>
+ProtectKernelTunables=<%= @protect_kernel_tunables %>
+<% end -%>
+<% if @protect_kernel_modules -%>
+ProtectKernelModules=<%= @protect_kernel_modules %>
+<% end -%>
+<% if @protect_kernel_logs -%>
+ProtectKernelLogs=<%= @protect_kernel_logs %>
+<% end -%>
+<% if @protect_control_groups -%>
+ProtectControlGroups=<%= @protect_control_groups %>
<% end -%>
<% if @restrict_address_families -%>
-RestrictAddressFamilies=<%= Array(@restrict_address_families).join(" ") %>
+RestrictAddressFamilies=<%= Array(@restrict_address_families).sort.uniq.join(" ") %>
<% end -%>
-<% if @no_new_privileges -%>
-NoNewPrivileges=<%= @no_new_privileges %>
+<% if @restrict_namespaces -%>
+RestrictNamespaces=<%= Array(@restrict_namespaces).sort.uniq.join(" ") %>
+<% end -%>
+<% if @lock_personality -%>
+LockPersonality=<%= @lock_personality %>
+<% end -%>
+<% if @memory_deny_write_execute -%>
+MemoryDenyWriteExecute=<%= @memory_deny_write_execute %>
+<% end -%>
+<% if @restrict_realtime -%>
+RestrictRealtime=<%= @restrict_realtime %>
+<% end -%>
+<% if @restrict_suid_sgid -%>
+RestrictSUIDSGID=<%= @restrict_suid_sgid %>
+<% end -%>
+<% if @remove_ipc -%>
+RemoveIPC=<%= @remove_ipc %>
+<% end -%>
+<% if @system_call_filter -%>
+SystemCallFilter=<%= Array(@system_call_filter).join(" ") %>
+<% end -%>
+<% if @system_call_architectures -%>
+SystemCallArchitectures=<%= Array(@system_call_architectures).sort.uniq.join(" ") %>
<% end -%>
<% if @tasks_max -%>
TasksMax=<%= @tasks_max %>
<% if @restart -%>
Restart=<%= @restart %>
<% end -%>
+<% if @restart_sec -%>
+RestartSec=<%= @restart_sec %>
+<% end -%>
+<% if @timeout_start_sec -%>
+TimeoutStartSec=<%= @timeout_start_sec %>
+<% end -%>
+<% if @timeout_stop_sec -%>
+TimeoutStopSec=<%= @timeout_stop_sec %>
+<% end -%>
+<% if @timeout_abort_sec -%>
+TimeoutAbortSec=<%= @timeout_abort_sec %>
+<% end -%>
<% if @timeout_sec -%>
TimeoutSec=<%= @timeout_sec %>
<% end -%>
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+[Unit]
+Description=<%= @description %>
+<% if @after -%>
+After=<%= Array(@after).join(" ") %>
+<% end -%>
+<% if @wants -%>
+Wants=<%= Array(@wants).join(" ") %>
+<% end -%>
+
+[Socket]
+<% Array(@listen_stream).each do |listen| -%>
+ListenStream=<%= listen %>
+<% end -%>
+<% Array(@listen_datagram).each do |listen| -%>
+ListenDatagram=<%= listen %>
+<% end -%>
+<% Array(@listen_sequential_packet).each do |listen| -%>
+ListenSequentialPacket=<%= listen %>
+<% end -%>
+<% Array(@listen_fifo).each do |listen| -%>
+ListenFIFO=<%= listen %>
+<% end -%>
+<% Array(@listen_special).each do |listen| -%>
+ListenSpecial=<%= listen %>
+<% end -%>
+<% Array(@listen_netlink).each do |listen| -%>
+ListenNetlink=<%= listen %>
+<% end -%>
+<% Array(@listen_message_queue).each do |listen| -%>
+ListenMessageQueue=<%= listen %>
+<% end -%>
+<% Array(@listen_usb_function).each do |listen| -%>
+ListenUSBFunction=<%= listen %>
+<% end -%>
+<% if @socket_protocol -%>
+SocketProtocol=<%= @socket_protocol %>
+<% end -%>
+<% if @bind_ipv6_only -%>
+BindIpv6Only=<%= @bind_ipv6_only %>
+<% end -%>
+<% if @backlog -%>
+Backlog=<%= @backlog %>
+<% end -%>
+<% if @bind_to_device -%>
+BindToDevice=<%= @bind_to_device %>
+<% end -%>
+<% if @socket_user -%>
+SocketUser=<%= @socket_user %>
+<% end -%>
+<% if @socket_group -%>
+SocketGroup=<%= @socket_group %>
+<% end -%>
+<% if @socket_mode -%>
+SocketMode=<%= sprintf("0%o", @socket_mode) %>
+<% end -%>
+<% if @directory_mode -%>
+DirectoryMode=<%= sprintf("0%o", @directory_mode) %>
+<% end -%>
+<% if @accept -%>
+Accept=<%= @accept %>
+<% end -%>
+<% if @writable -%>
+Writable=<%= @writable %>
+<% end -%>
+<% if @max_connections -%>
+MaxConnections=<%= @max_connections %>
+<% end -%>
+<% if @max_connections_per_source -%>
+MaxConnectionsPerSource=<%= @max_connections_per_source %>
+<% end -%>
+<% if @keep_alive -%>
+KeepAlive=<%= @keep_alive %>
+<% end -%>
+<% if @keep_alive_time_sec -%>
+KeepAliveTimeSec=<%= @keep_alive_time_sec %>
+<% end -%>
+<% if @keep_alive_interval_sec -%>
+KeepAliveIntervalSec=<%= @keep_alive_interval_sec %>
+<% end -%>
+<% if @keep_alive_probes -%>
+KeepAliveProbes=<%= @keep_alive_probes %>
+<% end -%>
+<% if @no_delay -%>
+NoDelay=<%= @no_delay %>
+<% end -%>
+<% if @priority -%>
+Priority=<%= @priority %>
+<% end -%>
+<% if @defer_accept_sec -%>
+DeferAcceptSec=<%= @defer_accept_sec %>
+<% end -%>
+<% if @receive_buffer -%>
+ReceiveBuffer=<%= @receive_buffer %>
+<% end -%>
+<% if @send_buffer -%>
+SendBuffer=<%= @send_buffer %>
+<% end -%>
+<% if @ip_tos -%>
+IpTos=<%= @ip_tos %>
+<% end -%>
+<% if @ip_ttl -%>
+IpTtl=<%= @ip_ttl %>
+<% end -%>
+<% if @mark -%>
+Mark=<%= @mark %>
+<% end -%>
+<% if @reuse_port -%>
+ReusePort=<%= @reuse_port %>
+<% end -%>
+<% if @pipe_size -%>
+PipeSize=<%= @pipe_size %>
+<% end -%>
+<% if @message_queue_max_messages -%>
+MessageQueueMaxMessages=<%= @message_queue_max_messages %>
+<% end -%>
+<% if @message_queue_message_size -%>
+MessageQueueMessageSize=<%= @message_queue_message_size %>
+<% end -%>
+<% if @free_bind -%>
+FreeBind=<%= @free_bind %>
+<% end -%>
+<% if @transparent -%>
+Transparent=<%= @transparent %>
+<% end -%>
+<% if @broadcast -%>
+Broadcast=<%= @broadcast %>
+<% end -%>
+<% if @pass_credentials -%>
+PassCredentials=<%= @pass_credentials %>
+<% end -%>
+<% if @pass_security -%>
+PassSecurity=<%= @pass_security %>
+<% end -%>
+<% if @tcp_congestion -%>
+TcpCongestion=<%= @tcp_congestion %>
+<% end -%>
+<% Array(@exec_start_pre).each do |exec| -%>
+ExecStartPre=<%= exec %>
+<% end -%>
+<% Array(@exec_start).each do |exec| -%>
+ExecStart=<%= exec %>
+<% end -%>
+<% Array(@exec_stop_post).each do |exec| -%>
+ExecStopPost=<%= exec %>
+<% end -%>
+<% Array(@exec_stop).each do |exec| -%>
+ExecStop=<%= exec %>
+<% end -%>
+<% if @timeout_sec -%>
+TimeoutSec=<%= @timeout_sec %>
+<% end -%>
+<% if @service -%>
+Service=<%= @service %>
+<% end -%>
+<% if @remove_on_stop -%>
+RemoveOnStop=<%= @remove_on_stop %>
+<% end -%>
+<% Array(@symlinks).each do |symlink| -%>
+Symlinks=<%= symlink %>
+<% end -%>
+<% if @file_descriptor_name -%>
+FileDescriptorName=<%= @file_descriptor_name %>
+<% end -%>
+<% if @trigger_limit_interval_sec -%>
+TriggerLimitIntervalSec=<%= @trigger_limit_interval_sec %>
+<% end -%>
+<% if @trigger_limit_burst -%>
+TriggerLimitBurst=<%= @trigger_limit_burst %>
+<% end -%>
+
+[Install]
+WantedBy=multi-user.target
supports "ubuntu"
depends "accounts"
depends "apache"
-depends "passenger"
depends "git"
+depends "passenger"
+depends "planet"
+depends "prometheus"
+depends "ruby"
include_recipe "accounts"
include_recipe "apache"
-include_recipe "passenger"
include_recipe "git"
+include_recipe "passenger"
+include_recipe "planet::current"
+include_recipe "prometheus"
+include_recipe "ruby"
package %w[
libsqlite3-dev
pbzip2
]
-ruby_version = node[:passenger][:ruby_version]
-
-package "ruby#{ruby_version}"
-
-gem_package "bundler#{ruby_version}" do
- package_name "bundler"
- version "~> 1.16.2"
- gem_binary "gem#{ruby_version}"
- options "--format-executable"
-end
-
apache_module "cache"
apache_module "cache_disk"
apache_module "headers"
mode "440"
end
+systemd_service "taginfo-update@" do
+ description "Taginfo update for %i"
+ wants "planet-update.service"
+ after "planet-update.service"
+ exec_start "/srv/%i/bin/update"
+ user "taginfo"
+ sandbox :enable_network => true
+ restrict_address_families "AF_UNIX"
+ read_write_paths [
+ "/srv/%i/data",
+ "/srv/%i/download",
+ "/srv/%i/sources",
+ "/var/log/taginfo/%i"
+ ]
+end
+
+systemd_timer "taginfo-update@" do
+ description "Taginfo update for %i"
+ on_calendar "01:37"
+end
+
node[:taginfo][:sites].each do |site|
site_name = site[:name]
site_aliases = Array(site[:aliases])
settings["opensearch"]["contact"] = "webmaster@openstreetmap.org"
settings["paths"]["bin_dir"] = "#{directory}/build/src"
settings["sources"]["download"] = ""
- settings["sources"]["create"] = "db languages projects wiki chronology"
+ settings["sources"]["create"] = "db languages projects wiki wikidata chronology"
settings["sources"]["db"]["planetfile"] = "/var/lib/planet/planet.osh.pbf"
settings["sources"]["chronology"]["osm_history_file"] = "/var/lib/planet/planet.osh.pbf"
settings["tagstats"]["geodistribution"] = "DenseMmapArray"
notifies :restart, "service[apache2]"
end
- execute "#{directory}/taginfo/Gemfile" do
+ bundle_install "#{directory}/taginfo" do
action :nothing
- command "bundle#{ruby_version} install"
- cwd "#{directory}/taginfo"
user "root"
group "root"
- subscribes :run, "gem_package[bundler#{ruby_version}]"
subscribes :run, "git[#{directory}/taginfo]"
notifies :restart, "passenger_application[#{directory}/taginfo/web/public]"
end
directory "#{directory}/taginfo/web/public"
variables :aliases => site_aliases
end
-end
-template "/usr/local/bin/taginfo-update" do
- source "taginfo-update.erb"
- owner "root"
- group "root"
- mode "755"
- variables :sites => node[:taginfo][:sites]
+ service "taginfo-update@#{site_name}.timer" do
+ action [:enable, :start]
+ end
+
+ prometheus_collector "taginfo-#{site_name}" do
+ interval "15m"
+ user "taginfo"
+ path "#{directory}/taginfo/sources/metrics.rb"
+ options "#{directory}/data"
+ end
end
SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
DocumentRoot <%= @directory %>
SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
RedirectPermanent / https://<%= @name %>/
<% end -%>
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
+++ /dev/null
-#!/bin/sh
-
-# DO NOT EDIT - This file is being maintained by Chef
-
-<% @sites.each do |site| -%>
-<% if site[:directory] -%>
-<%= site[:directory] %>/bin/update
-<% else -%>
-/srv/<%= site[:name] %>/bin/update
-<% end -%>
-<% end -%>
$ROOT/taginfo/sources/update_all.sh $ROOT/sources
-mv $ROOT/data/taginfo-* $ROOT/data/old
-mv $ROOT/sources/taginfo-*.db $ROOT/sources/*/taginfo-*.db $ROOT/data
+ln -f $ROOT/data/taginfo-* $ROOT/data/old
+mv -f $ROOT/sources/taginfo-*.db $ROOT/sources/*/taginfo-*.db $ROOT/data
mv $ROOT/sources/download/* $ROOT/download
-sudo PASSENGER_INSTANCE_REGISTRY_DIR=<%= node[:passenger][:instance_registry_dir] %> /usr/bin/passenger-config restart-app $ROOT/taginfo/web > /dev/null
+PASSENGER_INSTANCE_REGISTRY_DIR=<%= node[:passenger][:instance_registry_dir] %> /usr/bin/passenger-config restart-app $ROOT/taginfo/web > /dev/null
find $ROOT/sources/log -mtime +28 -delete
-default[:tile][:database][:cluster] = "12/main"
+default[:tile][:database][:cluster] = "14/main"
default[:tile][:database][:postgis] = "3"
default[:tile][:database][:node_file] = "/store/database/nodes"
default[:tile][:database][:multi_geometry] = true
default[:tile][:database][:style_file] = nil
default[:tile][:database][:tag_transform_script] = nil
-default[:tile][:replication][:url] = "https://planet.osm.org/replication/minute/"
+default[:tile][:mapnik] = "3.1"
+
+default[:tile][:replication][:url] = "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/planet/replication/minute"
default[:tile][:data] = {}
default[:tile][:styles] = {}
default[:postgresql][:versions] |= [node[:tile][:database][:cluster].split("/").first]
+default[:postgresql][:monitor_database] = "gis"
default[:accounts][:users][:tile][:status] = :role
+
+default[:apache][:event][:server_limit] = node.cpu_cores * 5 / 4
+default[:apache][:event][:max_request_workers] = node.cpu_cores * node[:apache][:event][:threads_per_child]
+default[:apache][:event][:max_spare_threads] = node.cpu_cores * node[:apache][:event][:threads_per_child]
+++ /dev/null
-#!/usr/bin/python3
-"""
-Expire meta tiles from a OSM change file by resetting their modified time.
-"""
-
-import argparse
-import os
-import osmium as o
-import pyproj
-
-EXPIRY_TIME = 946681200 # 2000-01-01 00:00:00
-# width/height of the spherical mercator projection
-SIZE = 40075016.6855784
-
-proj_transformer = pyproj.Transformer.from_crs('epsg:4326', 'epsg:3857', always_xy = True)
-
-class TileCollector(o.SimpleHandler):
-
- def __init__(self, node_cache, zoom):
- super(TileCollector, self).__init__()
- self.node_cache = o.index.create_map("dense_file_array," + node_cache)
- self.done_nodes = set()
- self.tile_set = set()
- self.zoom = zoom
-
- def add_tile_from_node(self, location):
- if not location.valid():
- return
-
- lat = max(-85, min(85.0, location.lat))
- x, y = proj_transformer.transform(location.lon, lat)
-
- # renormalise into unit space [0,1]
- x = 0.5 + x / SIZE
- y = 0.5 - y / SIZE
- # transform into tile space
- x = x * 2**self.zoom
- y = y * 2**self.zoom
- # chop of the fractional parts
- self.tile_set.add((int(x), int(y), self.zoom))
-
- def node(self, node):
- # we put all the nodes into the hash, as it doesn't matter whether the node was
- # added, deleted or modified - the tile will need updating anyway.
- self.done_nodes.add(node.id)
- self.add_tile_from_node(node.location)
-
- def way(self, way):
- for n in way.nodes:
- if not n.ref in self.done_nodes:
- self.done_nodes.add(n.ref)
- try:
- self.add_tile_from_node(self.node_cache.get(n.ref))
- except KeyError:
- pass # no coordinate
-
-
-def xyz_to_meta(x, y, z, meta_size):
- """ Return the file name of a meta tile.
- This must match the definition of xyz to meta in mod_tile.
- """
- # mask off the final few bits
- x = x & ~(meta_size - 1)
- y = y & ~(meta_size - 1)
-
- # generate the path
- path = None
- for i in range(0, 5):
- part = str(((x & 0x0f) << 4) | (y & 0x0f))
- x = x >> 4
- y = y >> 4
- if path is None:
- path = (part + ".meta")
- else:
- path = os.path.join(part, path)
-
- return os.path.join(str(z), path)
-
-
-def expire_meta(meta):
- """Expire the meta tile by setting the modified time back.
- """
- if os.path.exists(meta):
- print("Expiring " + meta)
- os.utime(meta, (EXPIRY_TIME, EXPIRY_TIME))
-
-
-def expire_meta_tiles(options):
- proc = TileCollector(options.node_cache, options.max_zoom)
- proc.apply_file(options.inputfile)
-
- tile_set = proc.tile_set
-
- # turn all the tiles into expires, putting them in the set
- # so that we don't expire things multiple times
- for z in range(options.min_zoom, options.max_zoom + 1):
- meta_set = set()
- new_set = set()
- for xy in tile_set:
- meta = xyz_to_meta(xy[0], xy[1], xy[2], options.meta_size)
-
- for tile_dir in options.tile_dir:
- meta_set.add(os.path.join(tile_dir, meta))
-
- # add the parent into the set for the next round
- new_set.add((int(xy[0]/2), int(xy[1]/2), xy[2] - 1))
-
- # expire all meta tiles
- for meta in meta_set:
- expire_meta(meta)
-
- # continue with parent tiles
- tile_set = new_set
-
-if __name__ == '__main__':
-
- parser = argparse.ArgumentParser(description=__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter,
- usage='%(prog)s [options] <inputfile>')
- parser.add_argument('--min', action='store', dest='min_zoom', default=13,
- type=int,
- help='Minimum zoom for expiry.')
- parser.add_argument('--max', action='store', dest='max_zoom', default=20,
- type=int,
- help='Maximum zoom for expiry.')
- parser.add_argument('-t', action='append', dest='tile_dir', default=None,
- required=True,
- help='Tile directory (repeat for multiple directories).')
- parser.add_argument('--meta-tile-size', action='store', dest='meta_size',
- default=8, type=int,
- help='The size of the meta tile blocks.')
- parser.add_argument('--node-cache', action='store', dest='node_cache',
- default='/store/database/nodes',
- help='osm2pgsql flatnode file.')
- parser.add_argument('inputfile',
- help='OSC input file.')
-
- options = parser.parse_args()
-
- expire_meta_tiles(options)
<cross-domain-policy>
<allow-access-from domain="*" secure="false" />
</cross-domain-policy>
-
Disallow: /21/
Disallow: /22/
Disallow: /23/
-
--- /dev/null
+{
+ "tilejson": "3.0.0",
+ "attribution": "© <a href='https://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors",
+ "name": "OpenStreetMap Standard",
+ "tiles": [
+ "https://tile.openstreetmap.org/{z}/{x}/{y}.png"
+ ],
+ "minzoom": 0,
+ "maxzoom": 19
+}
+++ /dev/null
-#!/usr/bin/ruby
-
-require "rubygems"
-require "proj4"
-require "xml/libxml"
-require "set"
-require "time"
-
-module Expire
- # projection object to go from latlon -> spherical mercator
- PROJ = Proj4::Projection.new(["+proj=merc", "+a=6378137", "+b=6378137",
- "+lat_ts=0.0", "+lon_0=0.0", "+x_0=0.0",
- "+y_0=0", "+k=1.0", "+units=m",
- "+nadgrids=@null", "+no_defs +over"])
-
- # width/height of the spherical mercator projection
- SIZE = 40075016.6855784
- # the size of the meta tile blocks
- METATILE = 8
- # the directory root for meta tiles
- HASH_ROOT = "/tiles/default/".freeze
- # node cache file
- NODE_CACHE_FILE = "/store/database/nodes".freeze
-
- # turns a spherical mercator coord into a tile coord
- def self.tile_from_merc(point, zoom)
- # renormalise into unit space [0,1]
- point.x = 0.5 + point.x / SIZE
- point.y = 0.5 - point.y / SIZE
- # transform into tile space
- point.x = point.x * 2**zoom
- point.y = point.y * 2**zoom
- # chop of the fractional parts
- [point.x.to_int, point.y.to_int, zoom]
- end
-
- # turns a latlon -> tile x,y given a zoom level
- def self.tile_from_latlon(latlon, zoom)
- # first convert to spherical mercator
- point = PROJ.forward(latlon)
- tile_from_merc(point, zoom)
- end
-
- # this must match the definition of xyz_to_meta in mod_tile
- def self.xyz_to_meta(x, y, z)
- # mask off the final few bits
- x &= ~(METATILE - 1)
- y &= ~(METATILE - 1)
- # generate the path
- hash_path = (0..4).collect do |i|
- (((x >> 4 * i) & 0xf) << 4) | ((y >> 4 * i) & 0xf)
- end.reverse.join("/")
- z.to_s + "/" + hash_path + ".meta"
- end
-
- # time to reset to, some very stupidly early time, before OSM started
- EXPIRY_TIME = Time.parse("2000-01-01 00:00:00")
-
- # expire the meta tile by setting the modified time back
- def self.expire_meta(meta)
- puts "Expiring #{meta}"
- File.utime(EXPIRY_TIME, EXPIRY_TIME, meta)
- end
-
- def self.expire(change_file, min_zoom, max_zoom, tile_dirs)
- do_expire(change_file, min_zoom, max_zoom) do |set|
- new_set = Set.new
- meta_set = Set.new
-
- # turn all the tiles into expires, putting them in the set
- # so that we don't expire things multiple times
- set.each do |xy|
- # this has to match the routine in mod_tile
- meta = xyz_to_meta(xy[0], xy[1], xy[2])
-
- # check each style working out what needs expiring
- tile_dirs.each do |tile_dir|
- meta_set.add(tile_dir + "/" + meta) if File.exist?(tile_dir + "/" + meta)
- end
-
- # add the parent into the set for the next round
- new_set.add([xy[0] / 2, xy[1] / 2, xy[2] - 1])
- end
-
- # expire all meta tiles
- meta_set.each do |meta|
- expire_meta(meta)
- end
-
- # return the new set, consisting of all the parents
- new_set
- end
- end
-
- def self.do_expire(change_file, min_zoom, max_zoom, &_)
- # read in the osm change file
- doc = XML::Document.file(change_file)
-
- # hash map to contain all the nodes
- nodes = {}
-
- # we put all the nodes into the hash, as it doesn't matter whether the node was
- # added, deleted or modified - the tile will need updating anyway.
- doc.find("//node").each do |node|
- lat = node["lat"].to_f
- lat = -85 if lat < -85
- lat = 85 if lat > 85
- point = Proj4::Point.new(Math::PI * node["lon"].to_f / 180,
- Math::PI * lat / 180)
- nodes[node["id"].to_i] = tile_from_latlon(point, max_zoom)
- end
-
- # now we look for all the ways that have changed and put all of their nodes into
- # the hash too. this will add too many nodes, as it is possible a long way will be
- # changed at only a portion of its length. however, due to the non-local way that
- # mapnik does text placement, it may stil not be enough.
- #
- # also, we miss cases where nodes are deleted from ways where that node is not
- # itself deleted and the coverage of the point set isn't enough to encompass the
- # change.
- node_cache = NodeCache.new(NODE_CACHE_FILE)
- doc.find("//way/nd").each do |node|
- node_id = node["ref"].to_i
-
- next if nodes.include? node_id
-
- # this is a node referenced but not added, modified or deleted, so it should
- # still be in the node cache.
- if (entry = node_cache[node_id])
- point = Proj4::Point.new(entry.lon, entry.lat)
- nodes[node_id] = tile_from_merc(point, max_zoom)
- end
- end
- node_cache.close
-
- # create a set of all the tiles at the maximum zoom level which are touched by
- # any of the nodes we've collected. we'll create the tiles at other zoom levels
- # by a simple recursion.
- set = Set.new nodes.values
-
- # expire tiles and shrink to the set of parents
- max_zoom.downto(min_zoom) do |_|
- # allow the block to work on the set, returning the set at the next
- # zoom level
- set = yield set
- end
- end
-
- # wrapper to access the osm2pgsql node cache
- class NodeCache
- # node cache entry
- class Node
- attr_reader :lon, :lat
-
- def initialize(lon, lat)
- @lat = lat.to_f / 100.0
- @lon = lon.to_f / 100.0
- end
- end
-
- # open the cache
- def initialize(filename)
- @cache = File.new(filename, "r")
-
- throw "Unexpected format" unless @cache.sysread(4).unpack("l").first == 1
- throw "Unexpected ID size" unless @cache.sysread(4).unpack("l").first == 8
-
- @max_id = @cache.sysread(8).unpack("q").first
- end
-
- # close the cache
- def close
- @cache.close
- end
-
- # lookup a node
- def [](id)
- if id <= @max_id
- offset = 16 + id * 8
-
- @cache.sysseek(offset)
-
- lon, lat = @cache.sysread(8).unpack("ll")
-
- node = Node.new(lon, lat) if lon != -2147483648 && lat != -2147483648
- end
-
- node
- end
- end
-end
depends "accounts"
depends "apache"
depends "git"
-depends "munin"
depends "nodejs"
depends "postgresql"
depends "prometheus"
depends "python"
+depends "ruby"
depends "systemd"
depends "tools"
include_recipe "accounts"
include_recipe "apache"
include_recipe "git"
-include_recipe "munin"
include_recipe "nodejs"
include_recipe "postgresql"
include_recipe "prometheus"
include_recipe "python"
+include_recipe "ruby"
include_recipe "tools"
blocks = data_bag_item("tile", "blocks")
+admins = data_bag_item("apache", "admins")
web_passwords = data_bag_item("web", "passwords")
apache_module "alias"
conf "tile.conf.erb"
end
+apache_conf "renderd" do
+ action :disable
+end
+
ssl_certificate node[:fqdn] do
domains [node[:fqdn], "tile.openstreetmap.org", "render.openstreetmap.org"]
notifies :reload, "service[apache2]"
ignore_failure true
end
-tilecaches = search(:node, "roles:tilecache").sort_by { |n| n[:hostname] }
fastlyips = JSON.parse(IO.read("#{Chef::Config[:file_cache_path]}/fastly-ip-list.json"))
+remote_file "#{Chef::Config[:file_cache_path]}/statuscake-locations.json" do
+ source "https://app.statuscake.com/Workfloor/Locations.php?format=json"
+ compile_time true
+ ignore_failure true
+end
+
+statuscakelocations = JSON.parse(IO.read("#{Chef::Config[:file_cache_path]}/statuscake-locations.json"))
+
apache_site "default" do
- action [:disable]
+ action :disable
+end
+
+apache_site "tileserver_site" do
+ action :disable
end
apache_site "tile.openstreetmap.org" do
template "apache.erb"
- variables :caches => tilecaches, :fastly => fastlyips["addresses"]
+ variables :fastly => fastlyips["addresses"] + fastlyips["ipv6_addresses"],
+ :statuscake => statuscakelocations.flat_map { |_, v| [v["ip"], v["ipv6"]] },
+ :admins => admins["hosts"]
end
template "/etc/logrotate.d/apache2" do
mode "755"
end
-package "renderd"
+tile_directories = node[:tile][:styles].collect do |_, style|
+ style[:tile_directories].collect { |directory| directory[:name] }
+end.flatten.sort.uniq
+
+package %w[
+ renderd
+ libgoogle-perftools4
+]
systemd_service "renderd" do
- description "Mapnik rendering daemon"
+ dropin "chef"
after "postgresql.service"
wants "postgresql.service"
- user "www-data"
- exec_start "/usr/bin/renderd -f"
- runtime_directory "renderd"
- standard_error "null"
+ environment "LD_PRELOAD" => "libtcmalloc.so.4"
limit_nofile 4096
- memory_max "32G"
- private_tmp true
- private_devices true
- private_network true
- protect_system "full"
- protect_home true
- no_new_privileges true
+ memory_high "80%"
+ memory_max "90%"
+ sandbox true
+ restrict_address_families "AF_UNIX"
+ read_write_paths tile_directories
+ system_call_filter ["@system-service", "mincore"]
restart "on-failure"
end
package %w[
python3-cairo
python3-mapnik
+ python3-pyproj
python3-setuptools
]
python_version "3"
end
-package %w[
- fonts-noto-cjk
- fonts-noto-hinted
- fonts-noto-unhinted
- fonts-hanazono
- ttf-unifont
-]
-
-["NotoSansArabicUI-Regular.ttf", "NotoSansArabicUI-Bold.ttf"].each do |font|
- remote_file "/usr/share/fonts/truetype/noto/#{font}" do
- action :create_if_missing
- source "https://github.com/googlei18n/noto-fonts/raw/master/hinted/#{font}"
- owner "root"
- group "root"
- mode "644"
- end
-end
-
directory "/srv/tile.openstreetmap.org/cgi-bin" do
owner "tile"
group "tile"
mode "755"
end
-template "/etc/cron.hourly/export" do
- source "export.cron.erb"
- owner "root"
- group "root"
- mode "755"
+systemd_service "export-cleanup" do
+ description "Cleanup stale export temporary files"
+ joins_namespace_of "apache2.service"
+ exec_start "find /tmp -ignore_readdir_race -name 'export??????' -mmin +60 -delete"
+ user "www-data"
+ sandbox true
+end
+
+systemd_timer "export-cleanup" do
+ description "Cleanup stale export temporary files"
+ on_boot_sec "60m"
+ on_unit_inactive_sec "60m"
+end
+
+service "export-cleanup.timer" do
+ action [:enable, :start]
end
directory "/srv/tile.openstreetmap.org/data" do
mode "755"
end
-package "mapnik-utils"
+package %w[
+ mapnik-utils
+ tar
+ unzip
+]
node[:tile][:data].each_value do |data|
url = data[:url]
end
if file =~ /\.tgz$/
- package "tar"
-
execute file do
action :nothing
command "tar -zxf #{file} -C #{directory}"
group "tile"
end
elsif file =~ /\.tar\.bz2$/
- package "tar"
-
execute file do
action :nothing
command "tar -jxf #{file} -C #{directory}"
group "tile"
end
elsif file =~ /\.zip$/
- package "unzip"
-
execute file do
action :nothing
command "unzip -qq -o #{file} -d #{directory}"
nodejs_package "carto"
+lowzoom_threads = node.cpu_cores - 1
+
systemd_service "update-lowzoom@" do
description "Low zoom tile update service for %i layer"
- conflicts "render-lowzoom.service"
user "tile"
+ exec_start_pre "+/bin/systemctl stop render-lowzoom.service"
exec_start "/bin/bash /usr/local/bin/update-lowzoom-%i"
runtime_directory "update-lowzoom-%i"
- private_tmp true
- private_devices true
- private_network true
- protect_system "full"
- protect_home true
- no_new_privileges true
+ sandbox true
+ restrict_address_families "AF_UNIX"
+ read_write_paths [
+ "/srv/tile.openstreetmap.org/tiles/%i",
+ "/var/log/tile"
+ ]
restart "on-failure"
end
owner "root"
group "root"
mode "755"
- variables :style => name
+ variables :style => name, :threads => lowzoom_threads
end
service "update-lowzoom@#{name}" do
details[:tile_directories].each do |directory|
directory directory[:name] do
- owner "www-data"
- group "www-data"
+ owner "_renderd"
+ group "_renderd"
mode "755"
end
directory[:min_zoom].upto(directory[:max_zoom]) do |zoom|
directory "#{directory[:name]}/#{zoom}" do
- owner "www-data"
- group "www-data"
+ owner "_renderd"
+ group "_renderd"
mode "755"
end
group "tile"
end
+ if details[:fonts_script]
+ execute details[:fonts_script] do
+ action :nothing
+ command details[:fonts_script]
+ cwd style_directory
+ user "tile"
+ group "tile"
+ subscribes :run, "git[#{style_directory}]"
+ end
+ end
+
execute "#{style_directory}/project.mml" do
action :nothing
- command "carto -a 3.0.0 project.mml > project.xml"
+ command "carto -a 3.0.22 project.mml > project.xml"
cwd style_directory
user "tile"
group "tile"
superuser true
end
+postgresql_user "pnorman" do
+ cluster node[:tile][:database][:cluster]
+ superuser true
+end
+
postgresql_user "tile" do
cluster node[:tile][:database][:cluster]
end
cluster node[:tile][:database][:cluster]
end
+postgresql_user "_renderd" do
+ cluster node[:tile][:database][:cluster]
+end
+
postgresql_database "gis" do
cluster node[:tile][:database][:cluster]
owner "tile"
only_if { node[:tile][:database][:hstore] }
end
-%w[geography_columns planet_osm_nodes planet_osm_rels planet_osm_ways raster_columns raster_overviews spatial_ref_sys].each do |table|
+%w[geography_columns planet_osm_nodes planet_osm_rels planet_osm_ways raster_columns raster_overviews].each do |table|
postgresql_table table do
cluster node[:tile][:database][:cluster]
database "gis"
end
end
-%w[geometry_columns planet_osm_line planet_osm_point planet_osm_polygon planet_osm_roads].each do |table|
+%w[geometry_columns planet_osm_line planet_osm_point planet_osm_polygon planet_osm_roads spatial_ref_sys].each do |table|
postgresql_table table do
cluster node[:tile][:database][:cluster]
database "gis"
owner "tile"
- permissions "tile" => :all, "www-data" => :select
+ permissions "tile" => :all, "www-data" => :select, "_renderd" => :select
end
end
if node[:tile][:database][:external_data_script]
execute node[:tile][:database][:external_data_script] do
- command "#{node[:tile][:database][:external_data_script]} -R www-data"
+ command "#{node[:tile][:database][:external_data_script]} -R _renderd"
cwd "/srv/tile.openstreetmap.org"
user "tile"
group "tile"
+ ignore_failure true
end
-end
-postgresql_munin "gis" do
- cluster node[:tile][:database][:cluster]
- database "gis"
+ Array(node[:tile][:database][:external_data_tables]).each do |table|
+ postgresql_table table do
+ cluster node[:tile][:database][:cluster]
+ database "gis"
+ owner "tile"
+ permissions "tile" => :all, "www-data" => :select, "_renderd" => :select
+ end
+ end
end
directory File.dirname(node[:tile][:database][:node_file]) do
file node[:tile][:database][:node_file] do
owner "tile"
- group "www-data"
+ group "_renderd"
mode "660"
end
package %w[
osm2pgsql
- ruby
osmium-tool
pyosmium
- python3-pyproj
]
-remote_directory "/usr/local/bin" do
- source "bin"
- owner "root"
- group "root"
+directory "/var/lib/replicate" do
+ owner "tile"
+ group "tile"
mode "755"
- files_owner "root"
- files_group "root"
- files_mode "755"
end
template "/usr/local/bin/expire-tiles" do
mode "755"
end
-directory "/var/lib/replicate" do
- owner "tile"
- group "tile"
- mode "755"
-end
-
directory "/var/lib/replicate/expire-queue" do
owner "tile"
- group "www-data"
+ group "_renderd"
mode "775"
end
owner "root"
group "root"
mode "755"
- variables :postgresql_version => postgresql_version.to_f
end
systemd_service "expire-tiles" do
description "Tile dirtying service"
type "simple"
- user "www-data"
+ user "_renderd"
exec_start "/usr/local/bin/expire-tiles"
- standard_output "null"
- private_tmp true
- private_devices true
- protect_system "full"
- protect_home true
- no_new_privileges true
+ nice 10
+ sandbox true
+ restrict_address_families "AF_UNIX"
+ read_write_paths tile_directories + [
+ "/var/lib/replicate/expire-queue"
+ ]
end
systemd_path "expire-tiles" do
subscribes :restart, "systemd_path[expire-tiles]"
end
+template "/usr/local/bin/replicate-post" do
+ source "replicate-post.erb"
+ owner "root"
+ group "root"
+ mode "755"
+end
+
+osm2pgsql_arguments = %w[
+ --number-processes=1
+ --log-progress=false
+ --expire-tiles=13-19
+ --expire-output=/var/lib/replicate/dirty-tiles.txt
+ ]
+
+osm2pgsql_arguments.append("--multi-geometry") if node[:tile][:database][:multi_geometry]
+osm2pgsql_arguments.append("--hstore") if node[:tile][:database][:hstore]
+osm2pgsql_arguments.append("--tag-transform-script=#{node[:tile][:database][:tag_transform_script]}") if node[:tile][:database][:tag_transform_script]
+
systemd_service "replicate" do
description "Rendering database replication service"
after "postgresql.service"
wants "postgresql.service"
user "tile"
exec_start "/usr/local/bin/replicate"
- private_tmp true
- private_devices true
- protect_system "full"
- protect_home true
- no_new_privileges true
+ sandbox :enable_network => true
+ restrict_address_families "AF_UNIX"
+ read_write_paths [
+ "/store/database/nodes",
+ "/var/lib/replicate"
+ ]
restart "on-failure"
end
subscribes :restart, "systemd_service[replicate]"
end
-template "/etc/logrotate.d/replicate" do
- source "replicate.logrotate.erb"
- owner "root"
- group "root"
- mode "644"
-end
-
template "/usr/local/bin/render-lowzoom" do
source "render-lowzoom.erb"
owner "root"
group "root"
mode "755"
+ variables :threads => lowzoom_threads
end
systemd_service "render-lowzoom" do
condition_path_exists_glob "!/run/update-lowzoom-*"
user "tile"
exec_start "/usr/local/bin/render-lowzoom"
- private_tmp true
- private_devices true
- private_network true
- protect_system "full"
- protect_home true
- no_new_privileges true
+ sandbox true
+ restrict_address_families "AF_UNIX"
+ read_write_paths "/var/log/tile"
end
systemd_timer "render-lowzoom" do
description "Render low zoom tiles"
- on_calendar "Sun *-*~07/1 01:00:00"
+ on_calendar "23:00 #{node[:timezone]}"
end
service "render-lowzoom.timer" do
mode "755"
end
-tile_directories = node[:tile][:styles].collect do |_, style|
- style[:tile_directories].collect { |directory| directory[:name] }
-end.flatten.sort.uniq
+systemd_service "cleanup-tiles@" do
+ description "Cleanup old tiles for /%I"
+ exec_start "/usr/local/bin/cleanup-tiles /%I"
+ user "_renderd"
+ io_scheduling_class "idle"
+ sandbox true
+ read_write_paths "/%I"
+end
+
+systemd_timer "cleanup-tiles@" do
+ description "Cleanup old tiles for /%I"
+ on_boot_sec "30m"
+ on_unit_inactive_sec "60m"
+ randomized_delay_sec "10m"
+end
tile_directories.each do |directory|
- label = directory.gsub("/", "-")
+ label = directory[1..].gsub("/", "-")
- cron_d "cleanup-tiles#{label}" do
- minute "0"
- user "www-data"
- command "ionice -c 3 /usr/local/bin/cleanup-tiles #{directory}"
- mailto "admins@openstreetmap.org"
+ service "cleanup-tiles@#{label}.timer" do
+ action [:enable, :start]
end
end
-munin_plugin "mod_tile_fresh"
-munin_plugin "mod_tile_latency"
-munin_plugin "mod_tile_response"
-munin_plugin "mod_tile_zoom"
-
-munin_plugin "renderd_processed"
-munin_plugin "renderd_queue"
-munin_plugin "renderd_queue_time"
-munin_plugin "renderd_zoom"
-munin_plugin "renderd_zoom_time"
-
-munin_plugin "replication_delay"
+package "ruby-webrick"
prometheus_exporter "modtile" do
port 9494
ScriptAlias /cgi-bin/ /srv/tile.openstreetmap.org/cgi-bin/
# Get the real remote IP for requests via a trusted proxy
- RemoteIPHeader X-Forwarded-For
-<% @caches.each do |cache| -%>
-<% cache.ipaddresses(:role => :external).sort.each do |address| -%>
- RemoteIPTrustedProxy <%= address %>
-<% end -%>
-<% end -%>
+ RemoteIPHeader Fastly-Client-IP
<% @fastly.sort.each do |address| -%>
RemoteIPTrustedProxy <%= address %>
<% end -%>
# Redirect ACME certificate challenges
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
+
+ # Restrict tile access to CDN nodes and admins
+ <LocationMatch ^/default/\d+/\d+/\d+\.png$>
+ Require expr "%{CONN_REMOTE_ADDR} != %{REMOTE_ADDR}"
+ # Fastly POPs
+<% @fastly.sort.each do |address| -%>
+ Require ip <%= address %>
+<% end -%>
+ # StatusCake monitoring
+<% @statuscake.sort.reject { |address| address.empty? }.each do |address| -%>
+ Require ip <%= address %>
+<% end -%>
+ # Administrators
+<% @admins.sort.each do |address| -%>
+ Require ip <%= address %>
+<% end -%>
+ # OSM Amsterdam IPv4
+ Require ip 184.104.179.128/27
+ # OSM Amsterdam IPv6
+ Require ip 2001:470:1:fa1::/64
+ # OSM Dublin IPv4
+ Require ip 184.104.226.96/27
+ # OSM Dublin IPv6
+ Require ip 2001:470:1:b3b::/64
+ # OSM UCL IPv4
+ Require ip 193.60.236.0/24
+ </LocationMatch>
</VirtualHost>
<VirtualHost *:80>
ServerAlias render.openstreetmap.org
ServerAdmin webmaster@openstreetmap.org
- # Get the real remote IP for requests via a trusted proxy
- RemoteIPHeader X-Forwarded-For
-<% @caches.each do |cache| -%>
-<% cache.ipaddresses(:role => :external).sort.each do |address| -%>
- RemoteIPTrustedProxy <%= address %>
-<% end -%>
-<% end -%>
-
# Setup logging
LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined_with_remoteip
CustomLog /var/log/apache2/access.log combined_with_remoteip
# DO NOT EDIT - This file is being maintained by Chef
args = [
-<% node[:tile][:styles].each do |name,details| -%>
- "-t", "/srv/tile.openstreetmap.org/tiles/<%= name %>",
-<% end -%>
- "--min", "13",
- "--max", "<%= node[:tile][:styles].collect { |n,d| d[:max_zoom] }.max %>"
+ "--socket=/var/run/renderd/renderd.sock",
+ "--tile-dir=/srv/tile.openstreetmap.org/tiles",
+ "--touch-from=13",
+ "--min-zoom=13"
]
-Dir.glob("/var/lib/replicate/expire-queue/changes-*.gz").sort.each do |f|
- system("/usr/local/bin/expire-tiles-single", *args, f) && File::unlink(f)
+Dir.glob("/var/lib/replicate/expire-queue/changes-*.txt").sort.each do |f|
+ <% node[:tile][:styles].each do |name,details| -%>
+ system("/usr/bin/render_expired", "--map=<%= name %>", *args, "--max-zoom=<%= details[:max_zoom] %>", :in=> f) &&
+ <% end -%>
+ File::unlink(f)
end
+++ /dev/null
-#!/bin/sh
-
-# DO NOT EDIT - This file is being maintained by Chef
-
-# Removes stale tmp files from the export tab
-exec find /tmp -ignore_readdir_race -name 'export??????' -mmin +60 -delete
import mapnik
import os
import pyotp
+import pyproj
import resource
import shutil
import signal
output_error("No format specified")
else:
# Create projection object
- prj = mapnik.Projection("+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs +over");
+ transformer = pyproj.Transformer.from_crs("EPSG:4326", "EPSG:3857", always_xy=True)
# Get the bounds of the area to render
bbox = [float(x) for x in form.getvalue("bbox").split(",")]
output_error("Invalid bounding box")
else:
# Project the bounds to the map projection
- bbox = mapnik.forward_(mapnik.Box2d(*bbox), prj)
+ bbox = mapnik.Box2d(*transformer.transform(bbox[0], bbox[1]),
+ *transformer.transform(bbox[2], bbox[3]))
# Get the style to use
style = form.getvalue("style", "default")
daily
size 1G
missingok
- rotate 28
+ rotate 14
compress
delaycompress
notifempty
--timestamp=${timestamp} \
--tile-dir=/srv/tile.openstreetmap.org/tiles \
--socket=/var/run/renderd/renderd.sock \
- --num-threads=<%= node[:cpu][:total] - 1 %> \
+ --num-threads=<%= @threads %> \
--map="<%= style %>" \
- --max-load=<%= node[:cpu][:total] %> \
+ --max-load=<%= node.cpu_cores - 1 %> \
--min-zoom=0 --max-zoom=12
}
[renderd]
socketname=/var/run/renderd/renderd.sock
-num_threads=<%= node[:cpu][:total] - 1 %>
+num_threads=<%= node.cpu_cores - 1 %>
tile_dir=/srv/tile.openstreetmap.org/tiles
stats_file=/var/run/renderd/renderd.stats
[mapnik]
-plugins_dir=/usr/lib/mapnik/3.0/input
+plugins_dir=/usr/lib/mapnik/<%= node[:tile][:mapnik] %>/input
font_dir=/usr/share/fonts
font_dir_recurse=true
<% node[:tile][:styles].each do |name,details| -%>
--- /dev/null
+#!/bin/sh -e
+
+# DO NOT EDIT - This file is being maintained by Chef
+
+sequence="$1"
+timestamp="$2"
+
+mv /var/lib/replicate/dirty-tiles.txt /var/lib/replicate/expire-queue/changes-${sequence}.txt
+
+echo "$sequence" > /var/lib/replicate/sequence.txt
+echo "$timestamp" > /var/lib/replicate/timestamp.txt
-#!/bin/bash
+#!/bin/sh
# DO NOT EDIT - This file is being maintained by Chef
-# Before running updates, the replication needs to be set up with the timestamp
-# set to the day of the latest planet dump. Setting to midnight ensures we get
-# conistent data after first run. osmosis --read-replication-interval-init is
-# used to initially create the state file
-
-# Define exit handler
-function onexit {
- [ -f sequence-prev.txt ] && mv sequence-prev.txt sequence.txt
-}
-
-# Send output to the log
-exec > /var/log/tile/replicate.log 2>&1
-
-# Change to the replication state directory
-cd /var/lib/replicate
-
-# Install exit handler
-trap onexit EXIT
-
-# Loop indefinitely
-while true
+while [ 1 = 1 ]
do
- # Work out the name of the next file
- file="changes-$(cat sequence.txt).osc.gz"
-
- # Save sequence file so we can rollback if an error occurs
- cp sequence.txt sequence-prev.txt
-
- # Fetch the next set of changes
- pyosmium-get-changes --server=<%= node[:tile][:replication][:url] %> --sequence-file=sequence.txt --outfile=${file}
-
- # Save exit status
- status=$?
-
- # Check for errors
- if [ $status -eq 0 ]
- then
- # Enable exit on error
- set -e
-
- # Log the new data
- echo "Fetched new data from $(cat sequence-prev.txt) to $(cat sequence.txt) into ${file}"
-
- # Apply the changes to the database
- osm2pgsql --database gis --slim --append --number-processes=1 \
-<% if node[:tile][:database][:node_file] -%>
- --flat-nodes=<%= node[:tile][:database][:node_file] %> \
-<% end -%>
+ /bin/osm2pgsql-replication update \
+ --database gis \
+ --post-processing /usr/local/bin/replicate-post \
+ -- \
+ --number-processes=1 \
+ --log-progress=false \
+ --expire-tiles=13-19 \
+ --expire-output=/var/lib/replicate/dirty-tiles.txt \
<% if node[:tile][:database][:multi_geometry] -%>
- --multi-geometry \
+ --multi-geometry \
<% end -%>
<% if node[:tile][:database][:hstore] -%>
- --hstore \
-<% end -%>
-<% if node[:tile][:database][:style_file] -%>
- --style=<%= node[:tile][:database][:style_file] %> \
+ --hstore \
<% end -%>
<% if node[:tile][:database][:tag_transform_script] -%>
- --tag-transform-script=<%= node[:tile][:database][:tag_transform_script] %> \
+ --tag-transform-script=<%= node[:tile][:database][:tag_transform_script] %>
<% end -%>
- ${file}
-
- # No need to rollback now
- rm sequence-prev.txt
-
- # Get buffer count
- buffers=$(osmium fileinfo --extended --get=data.buffers.count ${file})
-
- # If this diff has content mark it as the latest diff
- if [ $buffers -gt 0 ]
- then
- ln -f ${file} changes-latest.osc.gz
- fi
-
- # Queue these changes for expiry processing
- ln ${file} expire-queue/${file}
-
- # Delete old downloads
- find . -name 'changes-*.gz' -mmin +300 -exec rm -f {} \;
-
- # Disable exit on error
- set +e
- elif [ $status -eq 3 ]
- then
- # Log the lack of data
- echo "No new data available. Sleeping..."
-
- # Remove file, it will just be an empty changeset
- rm ${file}
-
- # Sleep for a short while
- sleep 30
- else
- # Log our failure to fetch changes
- echo "Failed to fetch changes - waiting a few minutes before retry"
-
- # Remove any output that was produced
- rm -f ${file}
- # Wait five minutes and have another go
- sleep 300
- fi
+ sleep 30
done
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-/var/log/tile/replicate.log {
- compress
- delaycompress
- notifempty
- postrotate
- /bin/systemctl try-restart replicate
- endscript
-}
--timestamp=$(stat -c %Y "/srv/tile.openstreetmap.org/styles/<%= @style %>/project.xml") \
--tile-dir=/srv/tile.openstreetmap.org/tiles \
--socket=/var/run/renderd/renderd.sock \
- --num-threads=<%= node[:cpu][:total] - 1 %> \
+ --num-threads=<%= @threads %> \
--map="<%= @style %>" \
- --max-load=<%= node[:cpu][:total] %> \
+ --max-load=<%= node.cpu_cores - 1 %> \
--min-zoom=0 --max-zoom=12
}
+++ /dev/null
-# tilecache cookbook
-
-This cookbook installs and configures the tile caches for the
-tile.openstreetmap.org tileservers.
+++ /dev/null
-default[:tilecache][:tile_parent] = "render.openstreetmap.org"
-
-# Per IP bucket refill rate
-default[:tilecache][:ip_bucket_refill] = 4096
-# Per IP bucket size
-default[:tilecache][:ip_bucket_size] = 67108864
-# Per Class C refill rate
-default[:tilecache][:net_bucket_refill] = 8192
-# Per Class C bucket size
-default[:tilecache][:net_bucket_size] = 134217728
-
-# Enable nginx cache
-default[:nginx][:cache][:proxy][:enable] = true
+++ /dev/null
-%{time_total},%{http_code},%{url_effective},%{time_namelookup},%{time_connect},%{time_appconnect},%{time_pretransfer},%{time_redirect},%{time_starttransfer}\n
+++ /dev/null
-name "tilecache"
-maintainer "OpenStreetMap Administrators"
-maintainer_email "admins@openstreetmap.org"
-license "Apache-2.0"
-description "Installs and configures a tile cache"
-
-version "1.0.0"
-supports "ubuntu"
-depends "fail2ban"
-depends "munin"
-depends "nginx"
-depends "ohai"
-depends "squid"
-depends "ssl"
+++ /dev/null
-#
-# Cookbook:: tilecache
-# Recipe:: default
-#
-# Copyright:: 2011, OpenStreetMap Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require "ipaddr"
-
-include_recipe "fail2ban"
-include_recipe "munin"
-include_recipe "nginx"
-include_recipe "squid"
-include_recipe "ssl"
-
-package "apache2" do
- action :remove
-end
-
-package %w[
- curl
- xz-utils
- openssl
-]
-
-# oathtool for QoS token
-package "oathtool"
-
-tilecaches = search(:node, "roles:tilecache").sort_by { |n| n[:hostname] }
-tilerenders = search(:node, "roles:tile").sort_by { |n| n[:hostname] }
-
-web_passwords = data_bag_item("web", "passwords")
-
-tilecaches.each do |cache|
- cache.ipaddresses(:family => :inet, :role => :external).sort.each do |address|
- firewall_rule "accept-squid" do
- action :accept
- family "inet"
- source "net:#{address}"
- dest "fw"
- proto "tcp:syn"
- dest_ports "3128"
- source_ports "1024:"
- end
-
- firewall_rule "accept-squid-icp" do
- action :accept
- family "inet"
- source "net:#{address}"
- dest "fw"
- proto "udp"
- dest_ports "3130"
- source_ports "3130"
- end
-
- firewall_rule "accept-squid-icp-reply" do
- action :accept
- family "inet"
- source "fw"
- dest "net:#{address}"
- proto "udp"
- dest_ports "3130"
- source_ports "3130"
- end
-
- firewall_rule "accept-squid-htcp" do
- action :accept
- family "inet"
- source "net:#{address}"
- dest "fw"
- proto "udp"
- dest_ports "4827"
- source_ports "4827"
- end
-
- firewall_rule "accept-squid-htcp-reply" do
- action :accept
- family "inet"
- source "fw"
- dest "net:#{address}"
- proto "udp"
- dest_ports "4827"
- source_ports "4827"
- end
- end
-end
-
-squid_fragment "tilecache" do
- template "squid.conf.erb"
- variables :caches => tilecaches, :renders => tilerenders
-end
-
-package "rsync"
-
-template "/etc/logrotate.d/squid" do
- source "logrotate.squid.erb"
- owner "root"
- group "root"
- mode "644"
-end
-
-nginx_site "default" do
- action [:delete]
-end
-
-template "/usr/local/bin/nginx_generate_tilecache_qos_map" do
- source "nginx_generate_tilecache_qos_map.erb"
- owner "root"
- group "root"
- mode "750"
- variables :totp_key => web_passwords["totp_key"]
-end
-
-cron_d "tilecache" do
- action :delete
-end
-
-cron_d "tilecache-generate-qos-map" do
- minute "0"
- user "root"
- command "/usr/local/bin/nginx_generate_tilecache_qos_map"
-end
-
-cron_d "tilecache-curl-time" do
- user "www-data"
- command "/srv/tilecache/tilecache-curl-time"
-end
-
-cron_d "tilecache-curl-time-cleanup" do
- minute "15"
- hour "0"
- user "www-data"
- command "/srv/tilecache/tilecache-curl-time-cleanup"
-end
-
-execute "execute_nginx_generate_tilecache_qos_map" do
- command "/usr/local/bin/nginx_generate_tilecache_qos_map"
- creates "/etc/nginx/conf.d/tile_qos_rates.map"
- action :run
-end
-
-ssl_certificate "tile.openstreetmap.org" do
- domains ["tile.openstreetmap.org",
- "a.tile.openstreetmap.org",
- "b.tile.openstreetmap.org",
- "c.tile.openstreetmap.org",
- "tile.osm.org",
- "a.tile.osm.org",
- "b.tile.osm.org",
- "c.tile.osm.org"]
- notifies :restart, "service[nginx]"
-end
-
-nginx_site "tile" do
- template "nginx_tile.conf.erb"
- variables :caches => tilecaches
-end
-
-template "/etc/logrotate.d/nginx" do
- source "logrotate.nginx.erb"
- owner "root"
- group "root"
- mode "644"
-end
-
-fail2ban_jail "squid" do
- maxretry 1000
-end
-
-tilerenders.each do |render|
- munin_plugin "ping_#{render[:fqdn]}" do
- target "ping_"
- conf "munin.ping.erb"
- conf_variables :host => render[:fqdn]
- end
-end
-
-directory "/srv/tilecache" do
- owner "root"
- group "root"
- mode "755"
-end
-
-directory "/srv/tilecache/data" do
- owner "www-data"
- group "www-data"
- mode "755"
-end
-
-cookbook_file "/srv/tilecache/tilecache-curl-time.txt" do
- source "tilecache-curl-time.txt"
- owner "root"
- group "root"
- mode "755"
-end
-
-template "/srv/tilecache/tilecache-curl-time" do
- source "tilecache-curl-time.erb"
- owner "root"
- group "root"
- mode "755"
- variables :caches => tilecaches, :renders => tilerenders
-end
-
-template "/srv/tilecache/tilecache-curl-time-cleanup" do
- source "tilecache-curl-time-cleanup.erb"
- owner "root"
- group "root"
- mode "755"
-end
-
-ohai_plugin "tilecache" do
- template "ohai.rb.erb"
-end
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-/var/log/nginx/*.log {
- daily
- missingok
- rotate 7
- compress
- delaycompress
- notifempty
- create 640 nginx adm
- sharedscripts
- postrotate
- [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
- endscript
-}
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-/var/log/squid/*.log {
- daily
- compress
- compresscmd /usr/bin/xz
- compressoptions --threads=<%= [ node[:cpu][:total] / 2, 1 ].max.ceil %>
- uncompresscmd /usr/bin/unxz
- compressext .xz
- rotate 2
- missingok
- nocreate
- sharedscripts
- postrotate
-<% if node[:lsb][:release].to_f < 20.04 -%>
- test ! -e /var/run/squid.pid || /usr/sbin/squid -k rotate
-<% else -%>
- test ! -e /run/squid/squid.pid || /usr/sbin/squid -k rotate
-<% end -%>
- endscript
- lastaction
- /usr/bin/rsync --preallocate /var/log/squid/access.log.1.xz ironbelly::logs/tile.openstreetmap.org/<%= node[:hostname] %>-`date -d "-1 days" +%Y-%m-%d`.xz || true
- endscript
-}
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-[ping_<%= @host %>]
-env.ping_args -c 1 -w 20
-env.ping_warn 0.5
-env.ping_crit 1.0
-env.packetloss_warn 10
-env.packetloss_crit 30
+++ /dev/null
-#!/bin/bash
-# DO NOT EDIT - This file is being maintained by Chef
-set -e
-
-NUM_TOKENS=4 # current + 4
-VALID_TOKEN=3600 # in seconds
-
-SECONDS_AGO=$((${NUM_TOKENS} * ${VALID_TOKEN}))
-OLD_TIME=$(/bin/date -u "+%Y-%m-%dT %H:%M:%S %z" -d "${SECONDS_AGO} seconds ago")
-QOS_TOKENS=($(/usr/bin/oathtool --totp --now="${OLD_TIME}" --window=${NUM_TOKENS} --time-step-size=${VALID_TOKEN}s -b "<%= @totp_key %>"))
-
-# ${qos_tokens[4]/[-1] } = OSM.org exclusive / current
-# ${qos_tokens[3]/[-2] } = OSM.org exclusive / stale
-# ${qos_tokens[2]/[-3] } = tile.openstreetmap.org default
-# ${qos_tokens[1]/[-4] } = stale ~ 1 hour
-# ${qos_tokens[0]} = expired
-
-# Test if number of tokens returned by oathtool is expected number
-if [ "${#QOS_TOKENS[@]}" -ne "$((${NUM_TOKENS}+1))" ]; then
- >&2 echo "ERROR: Unexpected number of tokens"
- exit 1
-fi
-
-QOS_TOKEN_OSM=${QOS_TOKENS[-1]} # Cookie set by openstreetmap.org
-QOS_TOKEN_OSM_STALE=${QOS_TOKENS[-2]} # Cookie set by openstreetmap.org stale
-QOS_TOKEN_DEFAULT=${QOS_TOKENS[-3]} # Cookie presented by tile.openstreetmap.org to browsers
-QOS_TOKEN_STALE=${QOS_TOKENS[-4]} # Cookie which has become stale and will be replaced
-
-if [ -z "$QOS_TOKEN_OSM" -o -z "$QOS_TOKEN_DEFAULT" -o -z "$QOS_TOKEN_STALE" ]; then
- >&2 echo "ERROR: Unexpected blank token"
- exit 2
-fi
-
-cat <<EOF >/etc/nginx/conf.d/tile_qos_rates.map
-default 8192; # Default Rate (No QoS cookie)
-"${QOS_TOKEN_STALE}" 24576; # Stale
-"${QOS_TOKEN_DEFAULT}" 24576; # Default
-"${QOS_TOKEN_OSM_STALE}" 32768; # Exclusive Stale
-"${QOS_TOKEN_OSM}" 32768; # Exclusive
-EOF
-
-cat <<EOF >/etc/nginx/conf.d/tile_qos_cookies.map
-default '_osm_totp_token=${QOS_TOKEN_DEFAULT}; Max-Age=${VALID_TOKEN}; Domain=openstreetmap.org; Path=/'; # Cookie Domain per RFC6265
-"${QOS_TOKEN_DEFAULT}" ''; # Do not Set-Cookie. # Default
-"${QOS_TOKEN_OSM_STALE}" ''; # Do not Set-Cookie. # Exclusive Stale
-"${QOS_TOKEN_OSM}" ''; # Do not Set-Cookie. # Exclusive
-EOF
-
-# Check config, reload config and fail safe
-# /etc/init.d/nginx configtest 2>/dev/null && /bin/systemctl try-reload-or-restart nginx
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-upstream tile_cache_backend {
- server 127.0.0.1:8080 weight=1000 max_fails=32;
- server 127.0.0.2:8080 weight=1000 max_fails=32;
-
- # Add the tile_siblings caches to relieve pressure if local squid failing
- # Balancer: round-robin
-<% server_weight = 1000 -%>
-<% Array(@node[:tilecache][:tile_siblings]).each do |cache_peer| -%>
-<% @caches.each do |cache| -%>
-<% if cache_peer == cache[:fqdn] -%>
-<% if cache[:hostname] != node[:hostname] -%>
-<% cache.ipaddresses(:family => :inet, :role => :external).sort.each do |address| -%>
- server <%= address %>:80 weight=<%= server_weight %> max_fails=32 backup; # Server <%= cache[:hostname] %>
-<% server_weight -= server_weight.div(2) -%>
-<% end -%>
-<% end -%>
-<% end -%>
-<% end -%>
-<% end -%>
-
- keepalive 128;
-}
-
-# Geo Map of tile caches
-geo $tile_cache {
- default "client";
-<% @caches.each do |cache| -%>
-<% cache.ipaddresses(:family => :inet, :role => :external).sort.each do |address| -%>
- <%= address %> "cache"; # <%= cache[:hostname] %>
-<% end -%>
-<% end -%>
-}
-
-# Rates table based on current cookie value
-# map $cookie__osm_totp_token $limit_rate_qos {
-# include /etc/nginx/conf.d/tile_qos_rates.map;
-# }
-
-# Set-Cookie table based on current cookie value
-# map $cookie__osm_totp_token $cookie_qos_token_set {
-# include /etc/nginx/conf.d/tile_qos_cookies.map;
-# }
-
-map $http_user_agent $approved_scraper {
- default 0; # Not approved
- '~^JOSM\/' 1; # JOSM
- '~^Mozilla\/5\.0\ QGIS\/' 1; # QGIS
-}
-
-map $http_user_agent $denied_scraper {
- default 0; # Not denied
- '' 1; # No User-Agent Set
- '-' 1;
-
- # Library defaults
- '~^Python\-urllib\/' 1;
- '~^python\-requests\/' 1;
- '~^node\-fetch\/' 1;
- '~^R$' 1;
- '~^Java\/' 1;
- '~^tiles$' 1;
- '~^okhttp\/' 1;
- '~^Microsoft-ATL-Native\/' 1;
- '/n software IPWorks HTTP/S Component - www.nsoftware.com' 1;
- '~^Wget\/' 1;
- 'java' 1;
-
- # Library defaults or fakes
- 'Android' 1;
- 'kc_android' 1;
- 'host' 1;
- '~^maptestapp' 1;
- 'Other' 1;
- 'osmdroid' 1;
- '~^tilelive-http' 1;
- '~^Java-http-client' 1;
-
- # Fakes
- 'Mozilla/4.0' 1;
- 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)' 1;
-
- # Bulk downloaders
- 'C# TilesDownloader' 1;
- 'MapDownloader' 1;
- '~^staticmaps' 1;
-
- # Overusage apps
- '~^runtastic' 1;
- '~^Where\ my\ children' 1;
- 'nossoonibusjp.android.crosswalk' 1;
- 'br.com.concisoti.potybus' 1;
- 'com.soft373.taptaxi' 1;
- 'com.kradac.ktxcore' 1;
- '~^ru.crowdsystems.topcontrol.knd' 1;
- 'pl.itaxi.driver' 1;
- 'net.uztaxi.driver' 1;
- 'OSMDroid/2.1 (its; rutaxi 3.28.0)' 1;
- 'com.helleniccomms.mercedes.driver' 1;
- 'ru.taximaster.www' 1;
- 'com.arobs.trackgps' 1;
- 'com.helleniccomms.asteras.driver' 1;
-
- # Malware
- 'Agent Smith' 1;
- # '~[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}' 1; # Fake UA
-}
-
-map $http_referer $denied_referer {
- default 0; # Not denied
- # Faked sites
- 'http://www.openstreetmap.org/' 1;
- 'http://www.openstreetmap.org' 1;
- 'https://www.openstreetmap.org' 1;
- 'http://openstreetmap.org/' 1;
- 'http://openstreetmap.org' 1;
- 'https://openstreetmap.org' 1;
- 'http://www.osm.org/' 1;
- 'http://www.osm.org' 1;
- 'http://osm.org/' 1;
- 'http://osm.org' 1;
- 'http://google.com' 1;
- 'http://www.google.com' 1;
- 'http://google.com/' 1;
- 'http://www.google.com/' 1;
- 'https://google.com' 1;
- 'https://www.google.com' 1;
- 'https://google.com/' 1;
- 'https://www.google.com/' 1;
- 'http://www.microsoft.com/' 1;
-
- # Overusing websites
- '~^https?://pmap\.kuku\.lu/' 1;
- '~^https?://[^.]*\.pmap\.kuku\.lu/' 1;
- '~^https?://fastpokemap\.com/' 1;
- '~^https?://[^.]*\.fastpokemap\.com/' 1;
- '~^https?://pkget\.com/' 1;
- '~^https?://[^.]*\.pkget\.com/' 1;
- '~^https?://twpkinfo\.com/' 1;
- '~^https?://[^.]*\.twpkinfo\.com/' 1;
- '~^https?://9db\.jp/' 1;
- '~^https?://[^.]*\.9db\.jp/' 1;
- '~^https?://clustrmaps\.com/' 1;
- '~^https?://[^.]*\.clustrmaps\.com/' 1;
- '~^https?://geoportal360\.pl/' 1;
- '~^https?://skelbiu\.lt/' 1;
- '~^https?://[^.]*\.skelbiu\.lt/' 1;
- '~^https?://wialon\.[^.]*/' 1; # wialon has many domains, so block them all
- '~^https?://[^.]*\.wialon\.[^.]*/' 1;
- '~^https?://gps-trace\.com/' 1;
- '~^https?://[^.]*\.gps-trace\.com/' 1;
- '~^https?://cellmapper\.net/' 1;
- '~^https?://[^.]*\.cellmapper\.net/' 1;
-}
-
-map $http_referer $censored_referer {
- default 0; # Not denied
- # Blocked on board instructions
- '~^https?://schiebt-sie-ab\.de/' 1;
- '~^https?://[^.]*\.schiebt-sie-ab\.de/' 1;
-}
-
-
-map $http_referer $osm_referer {
- default ''; # False
- '~^https:\/\/www\.openstreetmap\.org\/' 'osm'; # True
-}
-
-# Limit Cache-Control header to only approved User-Agents
-map $tile_cache$osm_referer$http_user_agent $limit_http_cache_control {
- default ''; # Unset Header
- '~^clientosmMozilla\/5\.0\ \(X11' $http_cache_control; # Pass Header
- '~^clientosmMozilla\/5\.0\ \(Windows' $http_cache_control; # Pass Header
- '~^clientosmMozilla\/5\.0\ \(iPhone' $http_cache_control; # Pass Header
- '~^clientosmMozilla\/5\.0\ \(Macintosh' $http_cache_control; # Pass Header
- '~^clientosmMozilla\/5\.0\ \(Linux' $http_cache_control; # Pass Header
-}
-
-# Limit Pragma header to only approved User-Agents
-map $tile_cache$osm_referer$http_user_agent $limit_http_pragma {
- default ''; # Unset Header
- '~^clientosmMozilla\/5\.0\ \(X11' $http_pragma; # Pass Header
- '~^clientosmMozilla\/5\.0\ \(Windows' $http_pragma; # Pass Header
- '~^clientosmMozilla\/5\.0\ \(iPhone' $http_pragma; # Pass Header
- '~^clientosmMozilla\/5\.0\ \(Macintosh' $http_pragma; # Pass Header
- '~^clientosmMozilla\/5\.0\ \(Linux' $http_pragma; # Pass Header
-}
-
-# Find Browser User-Agents which are not sending a referer.
-# Browsers with no referer could be due to Browser extension or website Referrer-Policy
-map $tile_cache$http_referer$scheme$http_user_agent $deny_missing_referer {
- default 0; # Not denied
- '~^clienthttpsMozilla\/5\.0\ \(X11' 1;
- '~^clienthttpsMozilla\/5\.0\ \(Windows' 1;
- '~^clienthttpsMozilla\/5\.0\ \(iPhone' 1;
- '~^clienthttpsMozilla\/5\.0\ \(Macintosh' 1;
- '~^clienthttpsMozilla\/5\.0\ \(Linux' 1;
-}
-
-server {
- # IPv4
- listen 80 deferred backlog=16384 reuseport default_server;
- listen 443 ssl deferred backlog=16384 reuseport http2 default_server;
- # IPv6
- listen [::]:80 deferred backlog=16384 reuseport default_server;
- listen [::]:443 ssl deferred backlog=16384 reuseport http2 default_server;
- server_name localhost;
-
- proxy_buffers 8 64k;
- proxy_busy_buffers_size 64k;
-
- ssl_certificate /etc/ssl/certs/tile.openstreetmap.org.pem;
- ssl_certificate_key /etc/ssl/private/tile.openstreetmap.org.key;
-
- # Requests sent within early data are subject to replay attacks.
- # See: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_early_data
- ssl_early_data on;
-
- # Immediately 404 layers we do not support
-<% for i in 20..99 do %>
- location /<%= i %>/ {
- return 404;
- }
-<% end %>
-
- # Immediately 404 silly tile requests
- location = /0/-1/-1.png {
- return 404;
- }
- location = /0/-1/0.png {
- return 404;
- }
- location = /0/-1/1.png {
- return 404;
- }
- location = /0/0/-1.png {
- return 404;
- }
- location = /0/0/1.png {
- return 404;
- }
- location = /0/0/2.png {
- return 404;
- }
- location = /0/1/-1.png {
- return 404;
- }
- location = /0/1/0.png {
- return 404;
- }
- location = /0/1/1.png {
- return 404;
- }
- location = /0/1/2.png {
- return 404;
- }
- location = /0/2/0.png {
- return 404;
- }
- location = /0/2/1.png {
- return 404;
- }
- location = /0/2/2.png {
- return 404;
- }
- location = /1/-1/-1.png {
- return 404;
- }
- location = /1/-1/0.png {
- return 404;
- }
- location = /1/-1/1.png {
- return 404;
- }
- location = /1/-1/2.png {
- return 404;
- }
- location = /1/0/-1.png {
- return 404;
- }
- location = /1/1/-1.png {
- return 404;
- }
- location = /1/2/-1.png {
- return 404;
- }
- location = /2/-1/0.png {
- return 404;
- }
- location = /2/-1/1.png {
- return 404;
- }
- location = /2/-1/2.png {
- return 404;
- }
- location = /2/-1/3.png {
- return 404;
- }
- location = /2/0/-1.png {
- return 404;
- }
- location = /2/1/-1.png {
- return 404;
- }
- location = /2/1/4.png {
- return 404;
- }
- location = /2/2/4.png {
- return 404;
- }
- location = /2/3/4.png {
- return 404;
- }
- location = /2/4/0.png {
- return 404;
- }
- location = /2/4/1.png {
- return 404;
- }
- location = /2/4/2.png {
- return 404;
- }
- location = /2/4/3.png {
- return 404;
- }
- location = /2/4/4.png {
- return 404;
- }
-
-<% for i in 0..16 do %>
-<% if i == 0 -%>
- # Default Fallback Location Handler (lowest)
- location / {
-<% elsif -%>
- # Dedicated zoom handler for caching
- location /<%= i %>/ {
-<% end %>
- # Only allow GET / HEAD / OPTIONS (CORS) requests
- limit_except GET HEAD OPTIONS {
- deny all;
- }
-
- proxy_pass http://tile_cache_backend;
- proxy_set_header X-Forwarded-For $remote_addr;
- proxy_http_version 1.1;
- proxy_set_header Connection '';
-
- proxy_connect_timeout 20s;
-
- proxy_next_upstream_tries 2;
-
- # Replace host header.
- proxy_set_header Host 'tile.openstreetmap.org';
- # Drop all request headers and request body
- proxy_pass_request_headers off;
- proxy_pass_request_body off;
-
- # Do not allow setting cookies from backends due to caching.
- proxy_ignore_headers Set-Cookie;
- proxy_hide_header Set-Cookie;
-
-<% if i != 0 -%>
- # Caching
- proxy_cache "proxy_cache_zone";
- proxy_cache_lock on;
- proxy_cache_valid 200 2d;
- proxy_cache_valid 404 15m;
- # Serve stale cache on errors or if updating
- proxy_cache_use_stale error timeout updating http_404 http_500 http_503 http_504;
- # If in cache as stale, serve stale and update in background
- proxy_cache_background_update on;
- # Workaround nginx async bug which causes stale cache replies to wait for the async backend cache update reply (seen in v1.16.0)
- keepalive_requests 0;
- # Enable revalidation using If-Modified-Since and If-None-Match for stale items
- proxy_cache_revalidate on;
- proxy_cache_min_uses 4;
-
- add_header x-cache-status "$upstream_cache_status - <%= node[:hostname] %>";
-<% else %>
- # Severely rate limit Browser UAs which are not sending a referer.
- # With no referer we do not know who is using tiles
- if ($deny_missing_referer) {
- set $limit_rate 1024;
- add_header x-cache-ratelimit "missing-referer";
- }
-<% end -%>
-
- # Set a QoS cookie if none presented (uses nginx Map)
- # add_header Set-Cookie $cookie_qos_token_set;
-<% if node[:ssl][:strict_transport_security] -%>
- # Ensure Strict-Transport-Security header is removed from proxied server responses
- proxy_hide_header Strict-Transport-Security;
-
- # Enable HSTS
- add_header Strict-Transport-Security "<%= node[:ssl][:strict_transport_security] %>" always;
-<% end -%>
-
- # QoS Traffic Rate see $limit_rate on http://nginx.org/en/docs/http/ngx_http_core_module.html
- # set $limit_rate $limit_rate_qos;
-
- # Allow Higher Traffic Rate from Approved User-Agents which do not support cookies (uses nginx Map)
- # if ($approved_scraper) {
- # set $limit_rate 65536;
- # }
-
- if ($denied_scraper) {
- set $limit_rate 512;
- return 429;
- }
- if ($denied_referer) {
- set $limit_rate 512;
- return 418;
- }
-
- if ($censored_referer) {
- set $limit_rate 512;
- return 451 "Unavailable at OSMF Board request";
- }
-
- # Strip any ?query parameters from urls
- set $args '';
-
- # Allow cache purging headers only from select User-Agents (uses nginx Map)
- proxy_set_header Cache-Control $limit_http_cache_control;
- proxy_set_header Pragma $limit_http_pragma;
- }
-<% end %>
-}
+++ /dev/null
-Ohai.plugin(:TileCache) do
- provides "tilecache"
-
- def tile_siblings
- recent = Time.now - 600
- times = Hash.new
-
- # Find performance reports for last few minutes
- # Add up total time taken to download tile grouped by remote server
- # Remove 1 second per successful time report (de-prioritise new servers)
- # Add 10 seconds per failed time report request
- Dir.glob("/srv/tilecache/data/**/tilecache-*.txt").each do |path|
- if File.mtime(path) > recent
- IO.readlines(path).reverse.take(20).each do |sample|
- if sample =~ %r{^(\d+\.\d+),(\d+),https://([^/]+)/} then
- time = Regexp.last_match(1).to_f
- status = Regexp.last_match(2).to_i
- host = Regexp.last_match(3)
-
- if status == 200 then
- times[host] = times.fetch(host, 0) + (time + 1) * (time + 1) - 1
- else
- times[host] = times.fetch(host, 0) + 10
- end
- end
- end
- end
- end
-
- # Sort time reports
- # Strip to best 4 server names
- times.to_a.sort_by(&:last).take(4).map(&:first)
- end
-
- collect_data(:default) do
- tilecache Mash.new
-
- tilecache[:tile_siblings] = tile_siblings
- end
-end
+++ /dev/null
-acl osmtile_thishost dstdomain <%= node.name %>
-acl osmtile_sites dstdomain <%= node.name %> a.tile.openstreetmap.org b.tile.openstreetmap.org c.tile.openstreetmap.org tile.openstreetmap.org a.tile.osm.org b.tile.osm.org c.tile.osm.org tile.osm.org
-acl osmtiles_png urlpath_regex .png$
-
-acl whitelist_path urlpath_regex ^/cgi-bin/(export|debug)
-acl blacklist_path urlpath_regex ^/cgi-bin/
-acl blacklist_path urlpath_regex ^/MyAdmin/
-acl blacklist_path urlpath_regex ^/myadmin/
-acl blacklist_path urlpath_regex ^/pma/
-acl blacklist_path urlpath_regex ^/phpmyadmin/
-acl blacklist_path urlpath_regex ^/phpMyAdmin/
-acl blacklist_path urlpath_regex ^/idssvc/
-acl blacklist_path urlpath_regex ^/iesvc/
-acl blacklist_path urlpath_regex ^/invoker/
-acl blacklist_path urlpath_regex ^/jmx-console/
-acl blacklist_path urlpath_regex ^/manager/
-acl blacklist_path urlpath_regex ^/service/
-acl blacklist_path urlpath_regex ^/web-console/
-acl blacklist_path urlpath_regex ^/wstats/
-acl blacklist_path urlpath_regex ^/zecmd/
-
-http_access allow osmtile_sites whitelist_path
-http_access deny blacklist_path
-
-acl requestMethodGet method GET
-
-http_access allow osmtile_sites requestMethodGet
-
-acl osmtile_nocache_url urlpath_regex \.png/(status|dirty)$
-cache deny osmtile_sites osmtile_nocache_url
-
-<% @caches.each do |cache| -%>
-<% cache.ipaddresses(:family => :inet, :role => :external).sort.each do |address| -%>
-acl tile_caches src <%= address %>
-<% end -%>
-<% end -%>
-
-# Primary Parent
-<% if node[:squid][:version] < 4 -%>
-cache_peer <%= node[:tilecache][:tile_parent] %> parent 443 0 no-query originserver name=osmtileAccel login=PASS connect-timeout=120 no-digest weight=1000 ssl ssldomain=render.openstreetmap.org
-<% elsif node[:lsb][:release].to_f < 20.04 -%>
-cache_peer <%= node[:tilecache][:tile_parent] %> parent 443 0 no-query originserver name=osmtileAccel login=PASS connect-timeout=120 no-digest weight=1000 tls tlsdomain=render.openstreetmap.org
-<% else -%>
-cache_peer <%= node[:tilecache][:tile_parent] %> parent 443 0 no-query originserver name=osmtileAccel login=PASS connect-timeout=120 no-digest weight=1000 tls tlsdomain=render.openstreetmap.org tls-options=NORMAL:-VERS-TLS1.3
-<% end -%>
-cache_peer_access osmtileAccel allow osmtile_sites
-
-# Backup Parents
-<% @renders.each do |renders| -%>
-<% if node[:squid][:version] < 4 -%>
-cache_peer <%= renders[:hostname] %>.render.openstreetmap.org parent 443 0 no-query originserver name=osmtileAccelBackup<%= renders[:hostname] %> login=PASS connect-timeout=60 no-digest weight=10 ssl ssldomain=render.openstreetmap.org
-<% elsif node[:lsb][:release].to_f < 20.04 -%>
-cache_peer <%= renders[:hostname] %>.render.openstreetmap.org parent 443 0 no-query originserver name=osmtileAccelBackup<%= renders[:hostname] %> login=PASS connect-timeout=60 no-digest weight=10 tls tlsdomain=render.openstreetmap.org
-<% else -%>
-cache_peer <%= renders[:hostname] %>.render.openstreetmap.org parent 443 0 no-query originserver name=osmtileAccelBackup<%= renders[:hostname] %> login=PASS connect-timeout=60 no-digest weight=10 tls tlsdomain=render.openstreetmap.org tls-options=NORMAL:-VERS-TLS1.3
-<% end -%>
-cache_peer_access osmtileAccelBackup<%= renders[:hostname] %> allow osmtile_sites
-<% end -%>
-
-# ----------------------------------
-
-<% if node[:squid][:version] < 4 -%>
-
-#Allow tile_caches HTCP access
-htcp_access allow tile_caches
-
-#Allow tile_caches ICP access
-icp_access allow tile_caches
-<% end %>
-
-#----------------------------------
+++ /dev/null
-#/bin/bash
-set -eu
-/usr/bin/find /srv/tilecache/data/ -type f -iname '*.txt' -mtime +7 -print0 | /usr/bin/xargs -0 -n 12 --no-run-if-empty -P 2 /usr/bin/xz -9e
+++ /dev/null
-#!/bin/bash
-sleep $[ ( $RANDOM % 20 ) + 1 ]
-mkdir -p /srv/tilecache/data/$(date --utc "+%Y/%m")
-# localhost
-curl -w "@/srv/tilecache/tilecache-curl-time.txt" -o /dev/null -s -k -4 \
---max-time 60 \
-'http://localhost:8080/19/262106/174485.png' \
--H 'authority: c.tile.openstreetmap.org' \
--H 'sec-fetch-dest: image' \
--H 'user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36' \
--H 'dnt: 1' \
--H 'accept: image/webp,image/apng,image/*,*/*;q=0.8' \
--H 'sec-fetch-site: same-site' \
--H 'sec-fetch-mode: no-cors' \
--H 'referer: https://www.openstreetmap.org/' \
--H 'accept-language: en-GB,en-US;q=0.9,en;q=0.8' \
---compressed >> /srv/tilecache/data/$(date --utc "+%Y/%m")/localhost-<%= node.name.split(".").first %>-$(date --utc "+%Y-%m-%dT%H").txt
-# render
-<% @renders.each do |render| -%>
-<% if render.name != node.name -%>
-<% render.ipaddresses(:family => :inet, :role => :external).sort.each do |address| -%>
- curl -w "@/srv/tilecache/tilecache-curl-time.txt" -o /dev/null -s -k -4 \
- --max-time 60 \
- 'https://<%= render.name %>/19/262106/174485.png' \
- -H 'authority: c.tile.openstreetmap.org' \
- -H 'sec-fetch-dest: image' \
- -H 'user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36' \
- -H 'dnt: 1' \
- -H 'accept: image/webp,image/apng,image/*,*/*;q=0.8' \
- -H 'sec-fetch-site: same-site' \
- -H 'sec-fetch-mode: no-cors' \
- -H 'referer: https://www.openstreetmap.org/' \
- -H 'accept-language: en-GB,en-US;q=0.9,en;q=0.8' \
- --compressed >> /srv/tilecache/data/$(date --utc "+%Y/%m")/render-<%= render.name.split(".").first %>-$(date --utc "+%Y-%m-%dT%H").txt
-<% end -%>
-<% end -%>
-<% end -%>
-# caches
-<% @caches.each do |cache| -%>
-<% if cache.name != node.name -%>
-<% cache.ipaddresses(:family => :inet, :role => :external).sort.each do |address| -%>
- curl -w "@/srv/tilecache/tilecache-curl-time.txt" -o /dev/null -s -k -4 \
- --max-time 60 \
- 'https://<%= cache.name %>/19/262106/174485.png' \
- -H 'authority: c.tile.openstreetmap.org' \
- -H 'sec-fetch-dest: image' \
- -H 'user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36' \
- -H 'dnt: 1' \
- -H 'accept: image/webp,image/apng,image/*,*/*;q=0.8' \
- -H 'sec-fetch-site: same-site' \
- -H 'sec-fetch-mode: no-cors' \
- -H 'referer: https://www.openstreetmap.org/' \
- -H 'accept-language: en-GB,en-US;q=0.9,en;q=0.8' \
- --compressed >> /srv/tilecache/data/$(date --utc "+%Y/%m")/tilecache-<%= cache.name.split(".").first %>-$(date --utc "+%Y-%m-%dT%H").txt
-<% end -%>
-<% end -%>
-<% end -%>
-default[:tilelog][:source_directory] = "/opt/tilelog"
-default[:tilelog][:input_directory] = "/store/logs/tile.openstreetmap.org"
+default[:accounts][:users][:planet][:status] = :role
+
default[:tilelog][:output_directory] = "/store/planet/tile_logs"
version "1.0.0"
supports "ubuntu"
-depends "git"
-depends "tools"
+depends "accounts"
+depends "planet"
+depends "python"
+depends "systemd"
# Cookbook:: tilelog
# Recipe:: default
#
-# Copyright:: 2014, OpenStreetMap Foundation
+# Copyright:: 2014-2022, OpenStreetMap Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# limitations under the License.
#
-include_recipe "git"
-include_recipe "tools"
+include_recipe "accounts"
+include_recipe "planet::aws"
+include_recipe "python"
-package %w[
- gcc
- g++
- make
- autoconf
- automake
- libboost-filesystem-dev
- libboost-program-options-dev
- libboost-system-dev
-]
+passwords = data_bag_item("tilelog", "passwords")
-tilelog_source_directory = node[:tilelog][:source_directory]
-tilelog_input_directory = node[:tilelog][:input_directory]
+tilelog_directory = "/opt/tilelog"
tilelog_output_directory = node[:tilelog][:output_directory]
-# resources for building the tile analysis binary
-git tilelog_source_directory do
- action :sync
- repository "https://github.com/zerebubuth/openstreetmap-tile-analyze.git"
- revision "live"
- user "root"
- group "root"
- notifies :run, "execute[tilelog-autogen]", :immediately
+python_virtualenv tilelog_directory do
+ interpreter "/usr/bin/python3"
end
-execute "tilelog-autogen" do
- action :nothing
- command "autoreconf -i"
- cwd tilelog_source_directory
- user "root"
- group "root"
- notifies :run, "execute[tilelog-configure]", :immediately
+python_package "tilelog" do
+ python_virtualenv tilelog_directory
+ python_version "3"
+ version "1.7.0"
end
-execute "tilelog-configure" do
- action :nothing
- command "./configure --with-boost-libdir=/usr/lib/x86_64-linux-gnu"
- cwd tilelog_source_directory
- user "root"
- group "root"
- notifies :run, "execute[tilelog-build]", :immediately
-end
-
-execute "tilelog-build" do
- action :nothing
- command "make"
- cwd tilelog_source_directory
- user "root"
- group "root"
+directory tilelog_output_directory do
+ user "planet"
+ group "planet"
+ mode "755"
+ recursive true
end
-# resources for running the tile analysis
template "/usr/local/bin/tilelog" do
source "tilelog.erb"
owner "root"
group "root"
mode "755"
- variables :analyze_bin => "#{tilelog_source_directory}/openstreetmap-tile-analyze",
- :input_dir => tilelog_input_directory,
- :output_dir => tilelog_output_directory
+ variables :output_dir => tilelog_output_directory,
+ :aws_key => passwords["aws_key"]
end
-cron_d "tilelog" do
- minute "17"
- hour "22"
- user "www-data"
- command "/usr/local/bin/tilelog"
- mailto "zerebubuth@gmail.com"
+systemd_service "tilelog" do
+ description "Tile log analysis"
+ user "planet"
+ exec_start "/usr/local/bin/tilelog"
+ nice 10
+ sandbox :enable_network => true
+ protect_home "tmpfs"
+ bind_paths "/home/planet"
+ read_write_paths tilelog_output_directory
end
-# resources related to the output of the analysis and where it
-# can be publicly downloaded.
-directory tilelog_output_directory do
- user "www-data"
- group "www-data"
- mode "755"
- recursive true
+systemd_timer "tilelog" do
+ description "Tile log analysis"
+ on_calendar "*-*-* 01:07:00"
+end
+
+service "tilelog.timer" do
+ action [:enable, :start]
end
#!/bin/sh
+set -e
-ANALYZE=<%= @analyze_bin %>
-LOGDIR=<%= @input_dir %>
-OUTDIR=<%= @output_dir %>
-if [ -z "$DATE" ]; then
- DATE=`date -d "1 day ago" "+%Y-%m-%d"`
+if [ -z "$DATE" ]
+then
+ DATE=$(date -u -d "1 day ago" "+%Y-%m-%d")
+ YEAR=$(date -u -d "1 day ago" "+%Y")
fi
-TMPDIR=`mktemp -d -t tmp.XXXXXXXXX`
-ORIGDIR=`pwd`
-clean_up() {
- cd $ORIGDIR
- rm -rf $TMPDIR
-}
+OUTDIR="<%= @output_dir %>"
+TMPDIR=$(mktemp -d -t tilelog.XXXXXXXXX)
-trap clean_up 0 HUP INT TERM
-cd $TMPDIR
+cd "$TMPDIR"
-mkdir db
-nice -n 19 $ANALYZE $LOGDIR/*-${DATE}.xz > analyze.log
-if [ -f tiles.txt ]; then
- nice -n 19 xz -9e -z tiles.txt
- mv tiles.txt.xz $OUTDIR/tiles-${DATE}.txt.xz
+export AWS_ACCESS_KEY_ID="AKIASQUXHPE7JFCFMOUP"
+export AWS_SECRET_ACCESS_KEY="<%= @aws_key %>"
+export AWS_REGION="eu-west-1"
-else
- cat analyze.log
-fi
+TILEFILE="tiles-${DATE}.txt.xz"
+HOSTFILE="hosts-${DATE}.csv"
+APPFILE="apps-${DATE}.csv"
+COUNTRYFILE="countries-${DATE}.csv"
+
+nice -n 19 /opt/tilelog/bin/tilelog --date "${DATE}" \
+ --generate-success --generate-minimise --generate-location \
+ --tile "${TILEFILE}" --host "${HOSTFILE}" --app "${APPFILE}" --country "${COUNTRYFILE}"
+
+mv "${TILEFILE}" "${HOSTFILE}" "${APPFILE}" "${COUNTRYFILE}" "${OUTDIR}"
+
+/opt/awscli/v2/current/bin/aws --profile=osm-pds-upload s3 cp --storage-class=INTELLIGENT_TIERING --no-progress "${OUTDIR}/${TILEFILE}" "s3://osm-planet-eu-central-1/tile_logs/standard_layer/tiles/${YEAR}/${TILEFILE}"
+/opt/awscli/v2/current/bin/aws --profile=osm-pds-upload s3 cp --storage-class=INTELLIGENT_TIERING --no-progress "${OUTDIR}/${HOSTFILE}" "s3://osm-planet-eu-central-1/tile_logs/standard_layer/hosts/${YEAR}/${HOSTFILE}"
+/opt/awscli/v2/current/bin/aws --profile=osm-pds-upload s3 cp --storage-class=INTELLIGENT_TIERING --no-progress "${OUTDIR}/${APPFILE}" "s3://osm-planet-eu-central-1/tile_logs/standard_layer/apps/${YEAR}/${APPFILE}"
+/opt/awscli/v2/current/bin/aws --profile=osm-pds-upload s3 cp --storage-class=INTELLIGENT_TIERING --no-progress "${OUTDIR}/${COUNTRYFILE}" "s3://osm-planet-eu-central-1/tile_logs/standard_layer/countries/${YEAR}/${COUNTRYFILE}"
+
+rm -rf "$TMPDIR"
+++ /dev/null
-# TimescaleDB Cookbook
-
-This cookbook configures TimescaleDB.
+++ /dev/null
-default[:timescaledb][:database_version] = "13"
-default[:timescaledb][:max_background_workers] = 8
-
-default[:apt][:sources] |= ["timescaledb"]
+++ /dev/null
-#
-# Cookbook:: timescaledb
-# Recipe:: default
-#
-# Copyright:: 2021, OpenStreetMap Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-include_recipe "apt"
-
-database_version = node[:timescaledb][:database_version]
-
-package %W[
- timescaledb-tools
- timescaledb-2-postgresql-#{database_version}
-]
-
-node.default_unless[:postgresql][:versions] = []
-node.default[:postgresql][:versions] |= [database_version]
-node.default[:postgresql][:monitor_tables] = false
-node.default_unless[:postgresql][:settings][database_version][:shared_preload_libraries] = []
-node.default[:postgresql][:settings][database_version][:shared_preload_libraries] |= ["timescaledb"]
-node.default_unless[:postgresql][:settings][database_version][:customized_options] = {}
-node.default[:postgresql][:settings][database_version][:customized_options]["timescaledb.max_background_workers"] = node[:timescaledb][:max_background_workers]
-
-include_recipe "postgresql"
rsyslog
cron
locales-all
+ systemd-coredump
+ vim
]
service "rsyslog" do
end
# Remove some unused and unwanted packages
-package %w[mlocate nano whoopsie] do
+package %w[mlocate whoopsie] do
action :purge
end
+++ /dev/null
-default[:accounts][:users][:trac][:status] = :role
+++ /dev/null
-# This trac is no more. It has ceased to be.
-User-agent: *
-Disallow: /
+++ /dev/null
-<html xmlns="http://www.w3.org/1999/xhtml"
- xmlns:py="http://genshi.edgewall.org/" py:strip="">
-
- <form py:match="div[@id='content' and @class='ticket']/form" py:attrs="select('@*')">
- <py:if test="req.environ['PATH_INFO'] == '/newticket' and (not 'preview' in req.args)">
- <p>Before opening a new ticket, please:</p>
- <ol>
- <li>Check that you're in the right place. This is the bug-tracker for many OpenStreetMap related projects but not everything uses this site, so check the following list to make sure there isn't a better place to raise your issue:
- <ul>
- <li>Raise JOSM issues <a href="http://josm.openstreetmap.de/">here</a>.</li>
- <li>Raise JXAPI issues <a href="https://github.com/iandees/xapi-servlet/issues">here</a>.</li>
- </ul>
- </li>
- <li><a href="/report/1?sort=created&asc=1">View the list of tickets</a> to make sure that your bug hasn't already been reported. You should also try <a href="/search">searching</a>.</li>
- <li>Enter your bug descriptively. <i>Be sure you set the 'component' field (e.g. "website" or "potlatch (Flash editor)") so that it goes to the right person</i></li>
- </ol>
- <p>You can also use this to request enhancements.</p>
- <h2>How to be a helpful bug reporter</h2>
- <p>Where you can, always provide "steps to reproduce" - in other words, a series of instructions that the developers can follow to reproduce your bug. The more you can do to pinpoint the problem, the more likely it'll be fixed.</p>
- <ol>
- <li>Give any pertinent details of your system (operating system and version, browser and version, etc.).</li>
- <li>If the problem is with a web page or web application, give its URL. If the problem is encountered with a particular set of data, say what (e.g. a location in <a class="wiki" href="/wiki/OpenStreetMap">OpenStreetMap</a>).</li>
- <li>Explain what you are doing, click-by-click.</li>
- <li>Explain what you expect to happen.</li>
- <li>Explain what is happening instead.</li>
- </ol>
- <script type="text/javascript">
- $(document).ready(function () {
- var c = document.createElement("option");
- $(c).attr("selected", "selected");
- $("#field-component").prepend(c);
-
- $("#propertyform").submit(function () {
- if ($("#field-component").val() == "") {
- alert("Please select a component!");
- return false;
- } else {
- return true;
- }
- });
- });
- </script>
- </py:if>
- ${select('*')}
- </form>
-
-</html>
+++ /dev/null
-#!/usr/bin/ruby
-
-require "net/http"
-require "uri"
-
-user = gets.chop
-pass = gets.chop
-
-request = Net::HTTP::Get.new("/api/0.6/user/details")
-request.basic_auth user, pass
-
-response = Net::HTTP.start("api.openstreetmap.org", :use_ssl => true) do |http|
- http.request(request)
-end
-
-exit!(0) if response.is_a?(Net::HTTPSuccess)
-exit!(1)
version "1.0.0"
supports "ubuntu"
-depends "accounts"
-depends "apache"
+depends "podman"
# limitations under the License.
#
-include_recipe "accounts"
-include_recipe "apache"
+include_recipe "podman::apache"
-package %w[
- trac
- ruby
-]
-
-site_name = "trac.openstreetmap.org"
-site_directory = "/srv/#{site_name}"
-
-directory "/var/lib/trac" do
- owner "trac"
- group "trac"
- mode "755"
-end
-
-execute "trac-initenv-#{site_name}" do
- command "trac-admin /var/lib/trac initenv #{site_name} sqlite:db/trac.db"
- user "trac"
- group "trac"
- not_if { ::File.exist?("/var/lib/trac/VERSION") }
-end
-
-template "/var/lib/trac/conf/trac.ini" do
- source "trac.ini.erb"
- owner "trac"
- group "www-data"
- mode "644"
- variables :name => site_name
-end
-
-remote_directory "/var/lib/trac/htdocs" do
- source "htdocs"
- owner "trac"
- group "trac"
- mode "755"
- files_owner "trac"
- files_group "trac"
- files_mode "644"
- purge true
-end
-
-remote_directory "/var/lib/trac/templates" do
- source "templates"
- owner "trac"
- group "trac"
- mode "755"
- files_owner "trac"
- files_group "trac"
- files_mode "644"
- purge true
-end
-
-execute "trac-deploy-#{site_name}" do
- command "trac-admin /var/lib/trac deploy #{site_directory}"
- user "root"
- group "root"
- not_if { ::File.exist?(site_directory) }
-end
-
-cookbook_file "/usr/local/bin/trac-authenticate" do
- owner "root"
- group "root"
- mode "755"
-end
-
-apache_module "wsgi"
-
-apache_module "authnz_external" do
- package "libapache2-mod-authnz-external"
-end
-
-ssl_certificate "trac.openstreetmap.org" do
- domains ["trac.openstreetmap.org", "trac.osm.org"]
- notifies :reload, "service[apache2]"
-end
-
-apache_site site_name do
- template "apache.erb"
- directory site_directory
- variables :user => "trac", :group => "trac", :aliases => ["trac.osm.org"]
-end
-
-template "/etc/sudoers.d/trac" do
- source "sudoers.erb"
- owner "root"
- group "root"
- mode "440"
-end
-
-template "/etc/cron.daily/trac-backup" do
- source "backup.cron.erb"
- owner "root"
- group "root"
- mode "755"
+podman_site "trac.openstreetmap.org" do
+ image "ghcr.io/openstreetmap/trac-website:latest"
+ aliases ["trac.osm.org"]
end
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-WSGIDaemonProcess <%= @name %> user=<%= @user %> group=<%= @group %> processes=4 threads=8 restart-interval=3600 inactivity-timeout=180 graceful-timeout=60 maximum-requests=2000
-
-<VirtualHost *:80>
- ServerName <%= @name %>
-<% @aliases.each do |alias_name| -%>
- ServerAlias <%= alias_name %>
-<% end -%>
- ServerAdmin webmaster@openstreetmap.org
-
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
- ErrorLog /var/log/apache2/<%= @name %>-error.log
-
- RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
- RedirectPermanent / https://<%= @name %>/
-</VirtualHost>
-<% unless @aliases.empty? -%>
-
-<VirtualHost *:443>
- ServerName <%= @aliases.first %>
-<% @aliases.drop(1).each do |alias_name| -%>
- ServerAlias <%= alias_name %>
-<% end -%>
- ServerAdmin webmaster@openstreetmap.org
-
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
- SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
-
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
- ErrorLog /var/log/apache2/<%= @name %>-error.log
-
- RedirectPermanent / https://<%= @name %>/
-</VirtualHost>
-<% end -%>
-
-<VirtualHost *:443>
- ServerName <%= @name %>
- ServerAdmin webmaster@openstreetmap.org
-
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
- SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
-
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
- ErrorLog /var/log/apache2/<%= @name %>-error.log
-
- DocumentRoot <%= @directory %>/htdocs
- Alias /robots.txt <%= @directory %>/htdocs/site/robots.txt
- WSGIScriptAlias / <%= @directory %>/cgi-bin/trac.wsgi
-
- WSGIProcessGroup <%= @name %>
-
- DefineExternalAuth osm pipe /usr/local/bin/trac-authenticate
-
- # Disable /timeline for now
- RedirectMatch 410 ^/timeline(.*)$
-
- <Location /login>
- AuthType Basic
- AuthName "OpenStreetMap Trac"
- AuthBasicProvider external
- AuthExternal osm
- Require valid-user
- </Location>
-</VirtualHost>
-
-<Directory <%= @directory %>/htdocs>
- Require all granted
-</Directory>
-
-<Directory <%= @directory %>/cgi-bin>
- Require all granted
-</Directory>
+++ /dev/null
-#!/bin/sh
-
-# DO NOT EDIT - This file is being maintained by Chef
-
-T=$(mktemp -d -t -p /var/tmp trac.XXXXXXXXXX)
-D=$(date +%Y-%m-%d)
-B=trac-$D.tar.gz
-
-trac-admin /var/lib/trac hotcopy $T/trac-$D > /dev/null
-
-export RSYNC_RSH="ssh -ax"
-
-nice tar --create --directory=$T trac-$D | nice gzip --rsyncable -9 > $T/$B
-nice rsync --preallocate --fuzzy $T/$B backup::backup
-
-rm -rf $T
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-# Allow subversion to notify trac of commits
-www-data ALL=(trac) NOPASSWD: /usr/bin/trac-admin /var/lib/trac changeset *
-
-# Allow git to notify trac of commits
-%git ALL=(trac) NOPASSWD: /usr/bin/trac-admin /var/lib/trac changeset *
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-[attachment]
-max_size = 262144
-max_zip_size = 2097152
-render_unsafe_content = false
-
-[browser]
-color_scale = True
-downloadable_paths = /trunk, /branches/*, /tags/*
-hide_properties = svk:merge
-intermediate_color =
-intermediate_point =
-newest_color = (255, 136, 136)
-oldest_color = (136, 136, 255)
-oneliner_properties = trac:summary
-render_unsafe_content = false
-wiki_properties = trac:description
-
-[changeset]
-max_diff_bytes = 10000000
-max_diff_files = 0
-wiki_format_messages = true
-
-[components]
-tracopt.ticket.deleter = enabled
-tracopt.versioncontrol.git.* = enabled
-tracopt.versioncontrol.svn.* = enabled
-
-[header_logo]
-alt = OpenStreetMap
-height = 80
-link = https://<%= @name %>/
-src = site/osm.png
-width = 228
-
-[inherit]
-htdocs_dir =
-plugins_dir =
-templates_dir =
-
-[intertrac]
-josm.compat = false
-josm.title = JOSM Trac
-josm.url = https://josm.openstreetmap.de
-
-[logging]
-log_file = trac.log
-# log_format = <inherited>
-log_level = INFO
-log_type = file
-
-[milestone]
-stats_provider = DefaultTicketGroupStatsProvider
-
-[mimeviewer]
-max_preview_size = 262144
-mime_map = text/x-dylan:dylan,text/x-idl:ice,text/x-ada:ads:adb
-mime_map_patterns = text/plain:README|INSTALL|COPYING.*
-pygments_default_style = trac
-pygments_modes =
-tab_width = 8
-treat_as_binary = application/octet-stream, application/pdf, application/postscript, application/msword,application/rtf,
-
-[notification]
-admit_domains =
-always_notify_owner = true
-always_notify_reporter = true
-always_notify_updater = true
-ambiguous_char_width = single
-batch_subject_template = $prefix Batch modify: $tickets_descr
-email_sender = SmtpEmailSender
-ignore_domains =
-mime_encoding = none
-sendmail_path = sendmail
-smtp_always_bcc =
-smtp_always_cc =
-smtp_default_domain =
-smtp_enabled = true
-smtp_from = trac@noreply.openstreetmap.org
-smtp_from_author = false
-smtp_from_name =
-smtp_password =
-smtp_port = 25
-smtp_replyto = trac@noreply.openstreetmap.org
-smtp_server = localhost
-smtp_subject_prefix = __default__
-smtp_user =
-ticket_subject_template = $prefix #$ticket.id: $summary
-use_public_cc = true
-use_short_addr = false
-use_tls = false
-
-[project]
-admin =
-admin_trac_url = .
-descr = OpenStreetMap is a free editable map of the whole world
-footer = Visit the map at<br /><a href="https://www.openstreetmap.org/">https://www.openstreetmap.org/</a>
-icon = site/osm.ico
-name = OpenStreetMap
-url = https://www.openstreetmap.org/
-
-[query]
-default_anonymous_query = status!=closed&cc~=$USER
-default_query = status!=closed&owner=$USER
-items_per_page = 100
-ticketlink_query = ?status=!closed
-
-[report]
-items_per_page = 100
-items_per_page_rss = 0
-
-[repositories]
-subversion.dir = /var/lib/subversion/repos/openstreetmap
-subversion.description = Legacy subversion repository
-subversion.type = svn
-subversion.url = https://svn.openstreetmap.org/
-subversion.hidden = true
-<% Dir.glob("/var/lib/git/*.git").sort.each do |repository| -%>
-<%= File.basename(repository, ".git") %>.dir = <%= repository %>
-<%= File.basename(repository, ".git") %>.description = <%= IO.read("#{repository}/description").strip %>
-<%= File.basename(repository, ".git") %>.type = git
-<%= File.basename(repository, ".git") %>.url = https://git.openstreetmap.org/public/<%= File.basename(repository) %>
-<% end -%>
-.alias = subversion
-
-[revisionlog]
-default_log_limit = 100
-graph_colors = ['#cc0', '#0c0', '#0cc', '#00c', '#c0c', '#c00']
-
-[roadmap]
-stats_provider = DefaultTicketGroupStatsProvider
-
-[search]
-# default_disabled_filters = <inherited>
-min_query_length = 3
-
-[sqlite]
-# extensions = <inherited>
-
-[svn]
-branches = trunk,branches/*
-tags = tags/*
-
-[ticket]
-default_cc =
-default_component =
-default_description =
-default_keywords =
-default_milestone =
-default_owner = < default >
-default_priority = minor
-default_resolution = fixed
-default_severity =
-default_summary =
-default_type = defect
-default_version =
-max_comment_size = 262144
-max_description_size = 262144
-preserve_newlines = default
-restrict_owner = false
-workflow = ConfigurableTicketWorkflow
-
-[ticket-workflow]
-accept = new,assigned,accepted,reopened -> accepted
-accept.operations = set_owner_to_self
-accept.permissions = TICKET_MODIFY
-leave = * -> *
-leave.default = 1
-leave.operations = leave_status
-reassign = new,assigned,accepted,reopened -> assigned
-reassign.operations = set_owner
-reassign.permissions = TICKET_MODIFY
-reopen = closed -> reopened
-reopen.operations = del_resolution
-reopen.permissions = TICKET_CREATE
-resolve = new,assigned,accepted,reopened -> closed
-resolve.operations = set_resolution
-resolve.permissions = TICKET_MODIFY
-
-[timeline]
-abbreviated_messages = True
-changeset_collapse_events = false
-changeset_long_messages = false
-changeset_show_files = 0
-default_daysback = 30
-max_daysback = 90
-newticket_formatter = oneliner
-ticket_show_details = false
-
-[trac]
-auth_cookie_lifetime = 0
-auth_cookie_path =
-authz_file =
-authz_module_name =
-auto_preview_timeout = 2.0
-auto_reload = False
-backup_dir = db
-base_url = https://<%= @name %>/
-check_auth_ip = false
-database = sqlite:db/trac.db
-debug_sql = False
-default_charset = utf-8
-default_dateinfo_format = relative
-genshi_cache_size = 128
-htdocs_location =
-ignore_auth_case = false
-jquery_location =
-jquery_ui_location =
-jquery_ui_theme_location =
-mainnav = wiki,timeline,roadmap,browser,tickets,newticket,search
-metanav = login,logout,prefs,help,about
-mysqldump_path = mysqldump
-never_obfuscate_mailto = false
-permission_policies = DefaultPermissionPolicy, LegacyAttachmentPolicy
-permission_store = DefaultPermissionStore
-pg_dump_path = pg_dump
-repository_dir =
-repository_sync_per_request = (default)
-repository_type = svn
-resizable_textareas = true
-secure_cookies = False
-show_email_addresses = false
-show_ip_addresses = false
-timeout = 20
-use_base_url_for_redirect = False
-
-[versioncontrol]
-allowed_repository_dir_prefixes =
-
-[wiki]
-ignore_missing_pages = false
-max_size = 262144
-render_unsafe_content = false
-safe_schemes = cvs, file, ftp, git, irc, http, https, news, sftp, smb, ssh, svn, svn+ssh
-split_page_names = false
-
This cookbook installs and configures the web frontend machines that power
[www.openstreetmap.org](https://www.openstreetmap.org). There are several recipes
-* `web::backend` - sets up the backend servers, used for processing longer-running requests
* `web::base` - sets up common storage configuration between all the machines
* `web::cgimap` - builds and configures [cgimap](https://github.com/openstreetmap/cgimap)
* `web::cleanup` - configures a cleanup script to be run daily
default[:web][:pid_directory] = "/run/web"
default[:web][:log_directory] = "/var/log/web"
default[:web][:primary_cluster] = false
+default[:web][:max_request_area] = 0.25
+default[:web][:max_number_of_nodes] = 50000
+default[:web][:max_number_of_way_nodes] = 2000
+default[:web][:max_number_of_relation_members] = 32000
default[:accounts][:users][:rails][:status] = :role
depends "apache"
depends "apt"
depends "chef"
+depends "fail2ban"
depends "geoipupdate"
depends "git"
depends "memcached"
-depends "munin"
-depends "nfs"
depends "nodejs"
depends "passenger"
+depends "ruby"
depends "systemd"
depends "tools"
+++ /dev/null
-#
-# Cookbook:: web
-# Recipe:: backend
-#
-# Copyright:: 2011, OpenStreetMap Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-node.default[:memcached][:ip_address] = node.internal_ipaddress
-
-include_recipe "memcached"
-include_recipe "apache"
-include_recipe "web::rails"
-include_recipe "web::cgimap"
-
-web_passwords = data_bag_item("web", "passwords")
-
-apache_module "remoteip"
-apache_module "rewrite"
-apache_module "proxy"
-apache_module "proxy_fcgi"
-apache_module "setenvif"
-
-apache_site "default" do
- action [:disable]
-end
-
-apache_site "www.openstreetmap.org" do
- template "apache.backend.erb"
- variables :status => node[:web][:status],
- :secret_key_base => web_passwords["secret_key_base"]
-end
-
-service "rails-jobs@storage" do
- action [:disable, :stop]
-end
-
-service "rails-jobs@traces" do
- action [:disable, :stop]
-end
# limitations under the License.
#
-node.default[:nfs]["/store/rails"] = {
- :host => node[:web][:fileserver],
- :path => "/store/rails"
-}
-
include_recipe "accounts"
-include_recipe "nfs"
directory node[:web][:base_directory] do
group "rails"
db_passwords = data_bag_item("db", "passwords")
package "openstreetmap-cgimap-bin" do
- action :upgrade
+ action :install
end
database_host = node[:web][:readonly_database_host] || node[:web][:database_host]
memcached_servers = node[:web][:memcached_servers] || []
cgimap_options = {
+ "CGIMAP_SOCKET" => "/run/cgimap/socket",
"CGIMAP_HOST" => database_host,
"CGIMAP_DBNAME" => "openstreetmap",
"CGIMAP_USERNAME" => "cgimap",
"CGIMAP_LOGFILE" => "#{node[:web][:log_directory]}/cgimap.log",
"CGIMAP_MEMCACHE" => memcached_servers.join(","),
"CGIMAP_RATELIMIT" => "204800",
- "CGIMAP_MAXDEBT" => "250"
+ "CGIMAP_MAXDEBT" => "250",
+ "CGIMAP_MODERATOR_RATELIMIT" => "1048576",
+ "CGIMAP_MODERATOR_MAXDEBT" => "1280",
+ "CGIMAP_MAP_AREA" => node[:web][:max_request_area],
+ "CGIMAP_MAP_NODES" => node[:web][:max_number_of_nodes],
+ "CGIMAP_MAX_WAY_NODES" => node[:web][:max_number_of_way_nodes],
+ "CGIMAP_MAX_RELATION_MEMBERS" => node[:web][:max_number_of_relation_members],
+ "CGIMAP_RATELIMIT_UPLOAD" => "true"
}
if %w[database_readonly api_readonly].include?(node[:web][:status])
type "forking"
environment_file cgimap_options
user "rails"
- exec_start "/usr/bin/openstreetmap-cgimap --daemon --port 8000 --instances 30"
+ group "www-data"
+ umask "0002"
+ exec_start "/usr/bin/openstreetmap-cgimap --daemon --instances 30"
exec_reload "/bin/kill -HUP $MAINPID"
+ runtime_directory "cgimap"
private_tmp true
private_devices true
protect_system "full"
include_recipe "web::base"
-ruby = "ruby#{node[:passenger][:ruby_version]}"
+ruby = "ruby#{node[:ruby][:version]}"
rails_directory = "#{node[:web][:base_directory]}/rails"
template "/etc/cron.daily/web-cleanup" do
include_recipe "memcached"
include_recipe "apache"
+include_recipe "fail2ban"
include_recipe "web::rails"
include_recipe "web::cgimap"
apache_module "proxy_fcgi"
apache_module "lbmethod_byrequests"
apache_module "lbmethod_bybusyness"
+apache_module "reqtimeout"
apache_module "rewrite"
apache_module "unique_id"
mode "644"
end
-service "rails-jobs@mailers" do
- action [:enable, :start]
- supports :restart => true
- subscribes :restart, "rails_port[www.openstreetmap.org]"
- subscribes :restart, "systemd_service[rails-jobs]"
+fail2ban_filter "apache-request-timeout" do
+ failregex '^<ADDR> .* "-" 408 .*$'
end
-service "rails-jobs@storage" do
- action [:enable, :start]
- supports :restart => true
- subscribes :restart, "rails_port[www.openstreetmap.org]"
- subscribes :restart, "systemd_service[rails-jobs]"
+fail2ban_jail "apache-request-timeout" do
+ filter "apache-request-timeout"
+ logpath "/var/log/apache2/access.log"
+ ports [80, 443]
end
-if node[:web][:primary_cluster]
+fail2ban_filter "apache-trackpoints-timeout" do
+ failregex '^<ADDR> .* "GET /api/0\.6/trackpoints\?.*" 408 .*$'
+end
+
+fail2ban_jail "apache-trackpoints-timeout" do
+ filter "apache-trackpoints-timeout"
+ logpath "/var/log/apache2/access.log"
+ ports [80, 443]
+ bantime "12h"
+ findtime "30m"
+end
+
+fail2ban_filter "apache-notes-search" do
+ failregex '^<ADDR> .* "GET /api/0\.6/notes/search\?q=abcde&.*$'
+end
+
+fail2ban_jail "apache-notes-search" do
+ filter "apache-notes-search"
+ logpath "/var/log/apache2/access.log"
+ ports [80, 443]
+end
+
+if %w[database_offline database_readonly].include?(node[:web][:status])
+ service "rails-jobs@mailers" do
+ action :stop
+ end
+
+ service "rails-jobs@storage" do
+ action :stop
+ end
+
service "rails-jobs@traces" do
+ action :stop
+ end
+else
+ service "rails-jobs@mailers" do
action [:enable, :start]
supports :restart => true
subscribes :restart, "rails_port[www.openstreetmap.org]"
- subscribes :restart, "systemd_service[rails-jobs]"
+ subscribes :restart, "systemd_service[rails-jobs@]"
end
-else
+
+ service "rails-jobs@storage" do
+ action [:enable, :start]
+ supports :restart => true
+ subscribes :restart, "rails_port[www.openstreetmap.org]"
+ subscribes :restart, "systemd_service[rails-jobs@]"
+ end
+
service "rails-jobs@traces" do
- action [:disable, :stop]
+ action [:enable, :start]
+ supports :restart => true
+ subscribes :restart, "rails_port[www.openstreetmap.org]"
+ subscribes :restart, "systemd_service[rails-jobs@]"
end
end
+
+template "/usr/local/bin/deliver-message" do
+ source "deliver-message.erb"
+ owner "rails"
+ group "rails"
+ mode "0700"
+ variables :secret_key_base => web_passwords["secret_key_base"]
+end
include_recipe "apt"
include_recipe "git"
include_recipe "geoipupdate"
-include_recipe "munin"
include_recipe "nodejs"
include_recipe "passenger"
+include_recipe "ruby"
include_recipe "tools"
include_recipe "web::base"
nodejs_package "svgo"
-template "/etc/cron.hourly/passenger" do
- cookbook "web"
- source "passenger.cron.erb"
- owner "root"
- group "root"
- mode "755"
-end
-
-ruby_version = node[:passenger][:ruby_version]
rails_directory = "#{node[:web][:base_directory]}/rails"
-piwik = data_bag_item("web", "piwik")
+matomo = data_bag_item("web", "matomo")
storage = {
"avatars" => {
"acl" => "public-read",
"cache_control" => "public, max-age=31536000, immutable"
}
+ },
+ "gps_traces" => {
+ "service" => "S3",
+ "access_key_id" => "AKIASQUXHPE7AMJQRFOS",
+ "secret_access_key" => web_passwords["aws_key"],
+ "region" => "eu-west-1",
+ "bucket" => "openstreetmap-gps-traces",
+ "use_dualstack_endpoint" => true,
+ "upload" => {
+ "acl" => "public-read",
+ "cache_control" => "public, max-age=31536000, immutable"
+ }
+ },
+ "gps_images" => {
+ "service" => "S3",
+ "access_key_id" => "AKIASQUXHPE7AMJQRFOS",
+ "secret_access_key" => web_passwords["aws_key"],
+ "region" => "eu-west-1",
+ "bucket" => "openstreetmap-gps-images",
+ "use_dualstack_endpoint" => true,
+ "upload" => {
+ "acl" => "public-read",
+ "cache_control" => "public, max-age=31536000, immutable"
+ }
}
}
+db_host = if node[:web][:status] == "database_readonly"
+ node[:web][:readonly_database_host]
+ else
+ node[:web][:database_host]
+ end
+
rails_port "www.openstreetmap.org" do
- ruby ruby_version
directory rails_directory
user "rails"
group "rails"
repository "https://git.openstreetmap.org/public/rails.git"
revision "live"
- database_host node[:web][:database_host]
+ database_host db_host
database_name "openstreetmap"
database_username "rails"
database_password db_passwords["rails"]
email_from "OpenStreetMap <web@noreply.openstreetmap.org>"
status node[:web][:status]
messages_domain "messages.openstreetmap.org"
- gpx_dir "/store/rails/gpx"
- attachments_dir "/store/rails/attachments"
log_path "#{node[:web][:log_directory]}/rails.log"
logstash_path "#{node[:web][:log_directory]}/rails-logstash.log"
memcache_servers node[:web][:memcached_servers]
potlatch2_key web_passwords["potlatch2_key"]
id_key web_passwords["id_key"]
+ id_application web_passwords["id_application"]
oauth_key web_passwords["oauth_key"]
- piwik_configuration "location" => piwik[:location],
- "site" => piwik[:site],
- "goals" => piwik[:goals].to_hash
+ oauth_application web_passwords["oauth_application"]
+ matomo_configuration "location" => matomo[:location],
+ "site" => matomo[:site],
+ "visitor_cookie_timeout" => matomo[:visitor_cookie_timeout],
+ "referral_cookie_timeout" => matomo[:referral_cookie_timeout],
+ "session_cookie_timeout" => matomo[:session_cookie_timeout],
+ "goals" => matomo[:goals].to_hash
google_auth_id "651529786092-6c5ahcu0tpp95emiec8uibg11asmk34t.apps.googleusercontent.com"
google_auth_secret web_passwords["google_auth_secret"]
google_openid_realm "https://www.openstreetmap.org"
facebook_auth_id "427915424036881"
facebook_auth_secret web_passwords["facebook_auth_secret"]
- windowslive_auth_id "0000000040153C51"
- windowslive_auth_secret web_passwords["windowslive_auth_secret"]
+ microsoft_auth_id "e34f14f1-f790-40f3-9fa4-3c5f1a027c38"
+ microsoft_auth_secret web_passwords["microsoft_auth_secret"]
github_auth_id "acf7da34edee99e35499"
github_auth_secret web_passwords["github_auth_secret"]
wikipedia_auth_id "e4fe0c2c5855d23ed7e1f1c0fa1f1c58"
wikipedia_auth_secret web_passwords["wikipedia_auth_secret"]
thunderforest_key web_passwords["thunderforest_key"]
+ tracestrack_key web_passwords["tracestrack_key"]
totp_key web_passwords["totp_key"]
csp_enforce true
trace_use_job_queue true
diary_feed_delay 12
storage_configuration storage
- storage_service "avatars"
- storage_url "https://openstreetmap-user-avatars.s3.dualstack.eu-west-1.amazonaws.com"
-end
-
-gem_package "bundler#{ruby_version}" do
- package_name "bundler"
- gem_binary "gem#{ruby_version}"
- options "--format-executable"
+ avatar_storage "avatars"
+ trace_file_storage "gps_traces"
+ trace_image_storage "gps_images"
+ trace_icon_storage "gps_images"
+ avatar_storage_url "https://openstreetmap-user-avatars.s3.dualstack.eu-west-1.amazonaws.com"
+ trace_image_storage_url "https://openstreetmap-gps-images.s3.dualstack.eu-west-1.amazonaws.com"
+ overpass_url "https://query.openstreetmap.org/query-features"
+ overpass_credentials true
+ signup_ip_per_day 24
+ signup_ip_max_burst 48
+ signup_email_per_day 1
+ signup_email_max_burst 2
+ doorkeeper_signing_key web_passwords["openid_connect_key"].join("\n")
+ user_account_deletion_delay 7 * 24
+ # Requests to modify the imagery blacklist should come from the DWG only
+ imagery_blacklist [
+ # Current Google imagery URLs have google or googleapis in the domain
+ ".*\\.google(apis)?\\..*/.*",
+ # Blacklist VWorld
+ "http://xdworld\\.vworld\\.kr:8080/.*",
+ # Blacklist here
+ ".*\\.here\\.com[/:].*",
+ # Blacklist Mapy.cz
+ ".*\\.mapy\\.cz.*",
+ # Blacklist Yandex
+ ".*\\.api-maps\\.yandex\\.ru/.*",
+ ".*\\.maps\\.yandex\\.net/.*"
+ ]
end
-bundle = if File.exist?("/usr/bin/bundle#{ruby_version}")
- "/usr/bin/bundle#{ruby_version}"
- else
- "/usr/local/bin/bundle#{ruby_version}"
- end
-
systemd_service "rails-jobs@" do
description "Rails job queue runner"
type "simple"
- environment "RAILS_ENV" => "production", "QUEUE" => "%I"
+ environment "RAILS_ENV" => "production",
+ "QUEUE" => "%I",
+ "SLEEP_DELAY" => "60",
+ "SECRET_KEY_BASE" => web_passwords["secret_key_base"]
user "rails"
working_directory rails_directory
- exec_start "#{bundle} exec rake jobs:work"
+ exec_start "#{node[:ruby][:bundle]} exec rails jobs:work"
restart "on-failure"
- private_tmp true
- private_devices true
- protect_system "full"
- protect_home true
- no_new_privileges true
+ nice 10
+ sandbox :enable_network => true
+ memory_deny_write_execute false
+ read_write_paths "/var/log/web"
end
package "libjson-xs-perl"
mode "755"
end
-gem_package "apachelogregex"
-gem_package "file-tail"
+gem_package "apachelogregex" do
+ gem_binary node[:ruby][:gem]
+end
+
+gem_package "file-tail" do
+ gem_binary node[:ruby][:gem]
+end
template "/usr/local/bin/api-statistics" do
source "api-statistics.erb"
user "rails"
group "adm"
exec_start "/usr/local/bin/api-statistics"
- private_tmp true
- private_devices true
- private_network true
- protect_system "full"
- protect_home true
- no_new_privileges true
+ nice 10
+ sandbox true
+ read_write_paths [
+ "/srv/www.openstreetmap.org/rails/tmp",
+ "/var/lib/prometheus/node-exporter"
+ ]
restart "on-failure"
end
subscribes :restart, "systemd_service[api-statistics]"
end
-gem_package "hpricot"
-
-munin_plugin "api_calls_status"
-munin_plugin "api_calls_num"
-
-munin_plugin "api_calls_#{node[:hostname]}" do
- target "api_calls_"
-end
-
-munin_plugin "api_waits_#{node[:hostname]}" do
- target "api_waits_"
+gem_package "hpricot" do
+ gem_binary node[:ruby][:gem]
end
include_recipe "web::base"
-ruby = "ruby#{node[:passenger][:ruby_version]}"
+ruby = "ruby#{node[:ruby][:version]}"
rails_directory = "#{node[:web][:base_directory]}/rails"
template "/usr/local/bin/statistics" do
variables :ruby => ruby, :directory => rails_directory
end
-cron_d "statistics" do
- minute "0"
- hour "0"
+systemd_service "web-statistics" do
+ description "Generate web statistics"
+ environment "RAILS_ENV" => "production",
+ "SECRET_KEY_BASE_DUMMY" => "1"
user "rails"
- command "/usr/local/bin/statistics"
+ working_directory rails_directory
+ exec_start "/usr/local/bin/statistics"
+ sandbox :enable_network => true
+ memory_deny_write_execute false
+ read_write_paths ["#{rails_directory}/tmp", "/var/log/web"]
+end
+
+systemd_timer "web-statistics" do
+ description "Generate web statistics"
+ on_calendar "00:00:00"
+end
+
+service "web-statistics.timer" do
+ action [:enable, :start]
end
default_action :create
property :site, String, :name_property => true
-property :ruby, String, :default => "2.3"
property :directory, String
property :user, String
property :group, String
property :memcache_servers, Array
property :potlatch2_key, String
property :id_key, String
+property :id_application, String
property :oauth_key, String
+property :oauth_application, String
property :nominatim_url, String
-property :osrm_url, String
+property :overpass_url, String
+property :overpass_credentials, [true, false], :default => false
property :google_auth_id, String
property :google_auth_secret, String
property :google_openid_realm, String
property :facebook_auth_id, String
property :facebook_auth_secret, String
-property :windowslive_auth_id, String
-property :windowslive_auth_secret, String
+property :microsoft_auth_id, String
+property :microsoft_auth_secret, String
property :github_auth_id, String
property :github_auth_secret, String
property :wikipedia_auth_id, String
property :wikipedia_auth_secret, String
property :thunderforest_key, String
+property :tracestrack_key, String
property :totp_key, String
property :csp_enforce, [true, false], :default => false
property :csp_report_url, String
-property :piwik_configuration, Hash
+property :matomo_configuration, Hash
+property :storage_service, String, :default => "local"
+property :storage_url, String
property :trace_use_job_queue, [true, false], :default => false
property :diary_feed_delay, Integer
property :storage_configuration, Hash, :default => {}
-property :storage_service, String, :default => "local"
-property :storage_url, String
+property :avatar_storage, String
+property :trace_file_storage, String
+property :trace_image_storage, String
+property :trace_icon_storage, String
+property :avatar_storage_url, String
+property :trace_image_storage_url, String
+property :trace_icon_storage_url, String
property :tile_cdn_url, String
+property :imagery_blacklist, Array
+property :signup_ip_per_day, Integer
+property :signup_ip_max_burst, Integer
+property :signup_email_per_day, Integer
+property :signup_email_max_burst, Integer
+property :doorkeeper_signing_key, String
+property :user_account_deletion_delay, Integer
action :create do
package %W[
- ruby#{new_resource.ruby}
- ruby#{new_resource.ruby}-dev
imagemagick
+ libvips42
nodejs
tzdata
]
libgd-dev
libarchive-dev
libbz2-dev
+ libyaml-dev
]
package %w[
libjpeg-turbo-progs
]
- gem_package "bundler#{new_resource.ruby}" do
- package_name "bundler"
- version "2.1.4"
- gem_binary "gem#{new_resource.ruby}"
- options "--format-executable"
- end
-
- gem_package "bundler#{new_resource.ruby}" do
- package_name "pkg-config"
- gem_binary "gem#{new_resource.ruby}"
- end
-
declare_resource :directory, rails_directory do
owner new_resource.user
group new_resource.group
depth 1
user new_resource.user
group new_resource.group
- notifies :restart, "passenger_application[#{rails_directory}]"
end
declare_resource :directory, "#{rails_directory}/tmp" do
:name => new_resource.database_name,
:username => new_resource.database_username,
:password => new_resource.database_password
- notifies :restart, "passenger_application[#{rails_directory}]"
end
application_yml = edit_file "#{rails_directory}/config/example.application.yml" do |line|
line.gsub!(/^( *)#geonames_username:.*$/, "\\1geonames_username: \"openstreetmap\"")
- line.gsub!(/^( *)#maxmind_database:.*$/, "\\1maxmind_database: \"/usr/share/GeoIP/GeoLite2-Country.mmdb\"")
+ line.gsub!(/^( *)#maxmind_database:.*$/, "\\1maxmind_database: \"#{node[:geoipupdate][:directory]}/GeoLite2-Country.mmdb\"")
if new_resource.gpx_dir
line.gsub!(/^( *)gpx_trace_dir:.*$/, "\\1gpx_trace_dir: \"#{new_resource.gpx_dir}/traces\"")
line.gsub!(/^( *)#id_key:.*$/, "\\1id_key: \"#{new_resource.id_key}\"")
end
+ if new_resource.id_application
+ line.gsub!(/^( *)#id_application:.*$/, "\\1id_application: \"#{new_resource.id_application}\"")
+ end
+
if new_resource.oauth_key
line.gsub!(/^( *)#oauth_key:.*$/, "\\1oauth_key: \"#{new_resource.oauth_key}\"")
end
+ if new_resource.oauth_application
+ line.gsub!(/^( *)#oauth_application:.*$/, "\\1oauth_application: \"#{new_resource.oauth_application}\"")
+ end
+
if new_resource.nominatim_url
line.gsub!(/^( *)nominatim_url:.*$/, "\\1nominatim_url: \"#{new_resource.nominatim_url}\"")
end
- if new_resource.osrm_url
- line.gsub!(/^( *)osrm_url:.*$/, "\\1osrm_url: \"#{new_resource.osrm_url}\"")
+ if new_resource.overpass_url
+ line.gsub!(/^( *)overpass_url:.*$/, "\\1overpass_url: \"#{new_resource.overpass_url}\"")
end
if new_resource.google_auth_id
line.gsub!(/^( *)#facebook_auth_secret:.*$/, "\\1facebook_auth_secret: \"#{new_resource.facebook_auth_secret}\"")
end
- if new_resource.windowslive_auth_id
- line.gsub!(/^( *)#windowslive_auth_id:.*$/, "\\1windowslive_auth_id: \"#{new_resource.windowslive_auth_id}\"")
- line.gsub!(/^( *)#windowslive_auth_secret:.*$/, "\\1windowslive_auth_secret: \"#{new_resource.windowslive_auth_secret}\"")
+ if new_resource.microsoft_auth_id
+ line.gsub!(/^( *)#microsoft_auth_id:.*$/, "\\1microsoft_auth_id: \"#{new_resource.microsoft_auth_id}\"")
+ line.gsub!(/^( *)#microsoft_auth_secret:.*$/, "\\1microsoft_auth_secret: \"#{new_resource.microsoft_auth_secret}\"")
end
if new_resource.github_auth_id
group new_resource.group
mode "664"
content application_yml
- notifies :restart, "passenger_application[#{rails_directory}]"
only_if { ::File.exist?("#{rails_directory}/config/example.application.yml") }
end
"logstash_path",
"potlatch2_key",
"id_key",
+ "id_application",
"oauth_key",
+ "oauth_application",
"nominatim_url",
- "osrm_url",
+ "overpass_url",
+ "overpass_credentials",
"google_auth_id",
"google_auth_secret",
"google_openid_realm",
"facebook_auth_id",
"facebook_auth_secret",
- "windowslive_auth_id",
- "windowslive_auth_secret",
+ "microsoft_auth_id",
+ "microsoft_auth_secret",
"github_auth_id",
"github_auth_secret",
"wikipedia_auth_id",
"wikipedia_auth_secret",
"thunderforest_key",
+ "tracestrack_key",
"totp_key",
"csp_enforce",
"csp_report_url",
"diary_feed_delay",
"storage_service",
"storage_url",
- "tile_cdn_url"
+ "avatar_storage",
+ "trace_file_storage",
+ "trace_image_storage",
+ "trace_icon_storage",
+ "avatar_storage_url",
+ "trace_image_storage_url",
+ "trace_icon_storage_url",
+ "tile_cdn_url",
+ "imagery_blacklist",
+ "signup_ip_per_day",
+ "signup_ip_max_burst",
+ "signup_email_per_day",
+ "signup_email_max_burst",
+ "doorkeeper_signing_key",
+ "user_account_deletion_delay"
).compact.merge(
"server_protocol" => "https",
"server_url" => new_resource.site,
"support_email" => "support@openstreetmap.org",
"email_return_path" => "bounces@openstreetmap.org",
"geonames_username" => "openstreetmap",
- "maxmind_database" => "/usr/share/GeoIP/GeoLite2-Country.mmdb"
+ "maxmind_database" => "#{node[:geoipupdate][:directory]}/GeoLite2-Country.mmdb",
+ "max_request_area" => node[:web][:max_request_area],
+ "max_number_of_nodes" => node[:web][:max_number_of_nodes],
+ "max_number_of_way_nodes" => node[:web][:max_number_of_way_nodes],
+ "max_number_of_relation_members" => node[:web][:max_number_of_relation_members],
+ "oauth_10_support" => false,
+ "oauth_10_registration" => false
)
if new_resource.memcache_servers
settings["gpx_image_dir"] = "#{new_resource.gpx_dir}/images"
end
+ if new_resource.matomo_configuration
+ settings["matomo"] = new_resource.matomo_configuration.to_h
+ end
+
file "#{rails_directory}/config/settings.local.yml" do
owner new_resource.user
group new_resource.group
content YAML.dump(storage_configuration)
end
- if new_resource.piwik_configuration
- file "#{rails_directory}/config/piwik.yml" do
- owner new_resource.user
- group new_resource.group
- mode "664"
- content YAML.dump(new_resource.piwik_configuration)
- end
- else
- file "#{rails_directory}/config/piwik.yml" do
- action :delete
- end
+ file "#{rails_directory}/config/piwik.yml" do
+ action :delete
end
- execute "#{rails_directory}/Gemfile" do
+ bundle_install "#{rails_directory}" do
action :nothing
- command "bundle#{new_resource.ruby} install"
- cwd rails_directory
user "root"
group "root"
environment "NOKOGIRI_USE_SYSTEM_LIBRARIES" => "yes"
- subscribes :run, "gem_package[bundler#{new_resource.ruby}]"
subscribes :run, "git[#{rails_directory}]"
- notifies :restart, "passenger_application[#{rails_directory}]"
end
- execute "#{rails_directory}/db/migrate" do
+ bundle_exec "#{rails_directory}/db/migrate" do
action :nothing
- command "bundle#{new_resource.ruby} exec rake db:migrate"
- cwd rails_directory
+ directory rails_directory
+ command "rails db:migrate"
user new_resource.user
group new_resource.group
subscribes :run, "git[#{rails_directory}]"
- notifies :restart, "passenger_application[#{rails_directory}]"
only_if { new_resource.run_migrations }
end
- package "yarnpkg" do
- only_if { new_resource.build_assets }
- end
-
- execute "#{rails_directory}/package.json" do
+ bundle_exec "#{rails_directory}/package.json" do
action :nothing
- command "bundle#{new_resource.ruby} exec rake yarn:install"
+ directory rails_directory
+ command "rails yarn:install"
environment "HOME" => rails_directory,
- "RAILS_ENV" => "production"
- cwd rails_directory
+ "RAILS_ENV" => "production",
+ "SECRET_KEY_BASE_DUMMY" => "1"
user new_resource.user
group new_resource.group
subscribes :run, "git[#{rails_directory}]"
only_if { new_resource.build_assets }
end
- execute "#{rails_directory}/app/assets/javascripts/i18n" do
+ bundle_exec "#{rails_directory}/app/assets/javascripts/i18n" do
action :nothing
- command "bundle#{new_resource.ruby} exec rake i18n:js:export"
+ directory rails_directory
+ command "rails i18n:js:export"
environment "HOME" => rails_directory,
- "RAILS_ENV" => "production"
- cwd rails_directory
+ "RAILS_ENV" => "production",
+ "SECRET_KEY_BASE_DUMMY" => "1"
user new_resource.user
group new_resource.group
subscribes :run, "git[#{rails_directory}]"
only_if { new_resource.build_assets }
end
- execute "#{rails_directory}/public/assets" do
+ bundle_exec "#{rails_directory}/public/assets" do
action :nothing
- command "bundle#{new_resource.ruby} exec rake assets:precompile"
+ directory rails_directory
+ command "rails assets:precompile"
environment "HOME" => rails_directory,
- "RAILS_ENV" => "production"
- cwd rails_directory
+ "RAILS_ENV" => "production",
+ "SECRET_KEY_BASE_DUMMY" => "1"
user new_resource.user
group new_resource.group
subscribes :run, "git[#{rails_directory}]"
subscribes :run, "file[create:#{rails_directory}/config/application.yml]"
subscribes :run, "file[#{rails_directory}/config/settings.local.yml]"
subscribes :run, "file[#{rails_directory}/config/storage.yml]"
- subscribes :run, "file[#{rails_directory}/config/piwik.yml]"
- subscribes :run, "execute[#{rails_directory}/package.json]"
- subscribes :run, "execute[#{rails_directory}/app/assets/javascripts/i18n]"
- notifies :restart, "passenger_application[#{rails_directory}]"
+ subscribes :run, "bundle_exec[#{rails_directory}/package.json]"
+ subscribes :run, "bundle_exec[#{rails_directory}/app/assets/javascripts/i18n]"
only_if { new_resource.build_assets }
end
passenger_application rails_directory do
action :nothing
+ subscribes :restart, "git[#{rails_directory}]"
+ subscribes :restart, "file[#{rails_directory}/config/database.yml]"
+ subscribes :restart, "file[create:#{rails_directory}/config/application.yml]"
+ subscribes :restart, "file[#{rails_directory}/config/settings.local.yml]"
+ subscribes :restart, "file[#{rails_directory}/config/storage.yml]"
+ subscribes :restart, "bundle_installl[#{rails_directory}]"
+ subscribes :restart, "bundle_exec[#{rails_directory}/db/migrate]"
+ subscribes :restart, "bundle_exec[#{rails_directory}/package.json]"
+ subscribes :restart, "bundle_exec[#{rails_directory}/app/assets/javascripts/i18n]"
+ subscribes :restart, "bundle_exec[#{rails_directory}/public/assets]"
only_if { ::File.exist?("/usr/bin/passenger-config") }
end
end
action_class do
- include Chef::Mixin::EditFile
+ include OpenStreetMap::Mixin::EditFile
def rails_directory
new_resource.directory || "/srv/#{new_resource.site}"
+++ /dev/null
-# DO NOT EDIT - This file is being maintained by Chef
-
-<VirtualHost *:443>
- #
- # Basic server configuration
- #
- ServerName <%= node[:fqdn] %>
- ServerAlias api.openstreetmap.org www.openstreetmap.org
- ServerAdmin webmaster@openstreetmap.org
-
- #
- # Enable SSL
- #
- SSLEngine on
- SSLCertificateFile /etc/ssl/certs/www.openstreetmap.org.pem
- SSLCertificateKeyFile /etc/ssl/private/www.openstreetmap.org.key
-
- #
- # Setup logging
- #
- LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" %Dus %{UNIQUE_ID}e %{SSL_PROTOCOL}x %{SSL_CIPHER}x" combined_with_time
- CustomLog /var/log/apache2/access.log combined_with_time
- ErrorLog /var/log/apache2/error.log
-
- #
- # Turn on the rewrite engine
- #
- RewriteEngine on
-
- #
- # Recover the unique ID from the request headers
- #
- SetEnvIf X-Request-Id ^(.*)$ UNIQUE_ID=$1
-
- #
- # Configure rails
- #
- DocumentRoot <%= node[:web][:base_directory] %>/rails/public
- RailsEnv production
- PassengerMinInstances 3
- PassengerMaxRequests 500
- PassengerPreStart https://www.openstreetmap.org/
- PassengerAppGroupName rails
- SetEnv OPENSTREETMAP_STATUS <%= @status %>
- SetEnv SECRET_KEY_BASE <%= @secret_key_base %>
-
- #
- # Get the real remote IP for requests via a trusted proxy
- #
- RemoteIPHeader X-Forwarded-For
- RemoteIPTrustedProxy 10.0.32.0/24
- RemoteIPTrustedProxy 10.0.48.0/24
-
- #
- # Pass authentication related headers to cgimap
- #
- <Location />
- CGIPassAuth On
- </Location>
-
- #
- # Pass supported calls to cgimap
- #
- RewriteRule ^/api/0\.6/map(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
- RewriteCond %{REQUEST_METHOD} ^(HEAD|GET)$
- RewriteRule ^/api/0\.6/(node|way|relation|changeset)/[0-9]+(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
- RewriteRule ^/api/0\.6/(node|way|relation)/[0-9]+/history(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
- RewriteRule ^/api/0\.6/(node|way|relation)/[0-9]+/relations(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
- RewriteRule ^/api/0\.6/node/[0-9]+/ways(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
- RewriteRule ^/api/0\.6/(way|relation)/[0-9]+/full(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
- RewriteRule ^/api/0\.6/(nodes|ways|relations)(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
- RewriteRule ^/api/0\.6/changeset/[0-9]+/(upload|download)(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
-</VirtualHost>
-
-<Directory <%= node[:web][:base_directory] %>/rails/public>
- Require all granted
-</Directory>
# DO NOT EDIT - This file is being maintained by Chef
+#
+# Setup logging
+#
+SetEnvIfNoCase Authorization "^Basic " AUTH_METHOD=basic
+SetEnvIfNoCase Authorization "^OAuth " AUTH_METHOD=oauth1
+SetEnvIfNoCase Authorization "^Bearer " AUTH_METHOD=oauth2
+SetEnvIfExpr "%{QUERY_STRING} =~ /(^|&)oauth_signature=/" AUTH_METHOD=oauth1
+LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" %Dus %{UNIQUE_ID}e %{SSL_PROTOCOL}x %{SSL_CIPHER}x %{AUTH_METHOD}e" combined_with_time
+CustomLog /var/log/apache2/access.log combined_with_time
+ErrorLog /var/log/apache2/error.log
+
<VirtualHost *:443>
#
# Basic server configuration
SSLCertificateFile /etc/ssl/certs/www.openstreetmap.org.pem
SSLCertificateKeyFile /etc/ssl/private/www.openstreetmap.org.key
- #
- # Setup logging
- #
- LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" %Dus %{UNIQUE_ID}e %{SSL_PROTOCOL}x %{SSL_CIPHER}x" combined_with_time
- CustomLog /var/log/apache2/access.log combined_with_time
- ErrorLog /var/log/apache2/error.log
-
#
# Turn on various features
#
ExpiresActive On
RewriteEngine on
+ #
+ # Configure timeouts
+ #
+ TimeOut 10
+ RequestReadTimeout handshake=10-20,MinRate=500 header=10-20,MinRate=500 body=10-120,MinRate=500
+ LogLevel reqtimeout:info
+
#
# Add the unique ID to the request headers
#
RewriteCond %{HTTP_USER_AGENT} "OSMApp Tuner"
RewriteRule . - [F,L]
+ #
+ # Block trace scraper
+ #
+ RewriteCond %{HTTP_USER_AGENT} "python-httpx/0.24.1"
+ RewriteRule . - [F,L]
+
+ #
+ # Block out of control spider
+ #
+ RewriteCond %{HTTP_USER_AGENT} "Bytespider"
+ RewriteRule . - [F,L]
+
#
# Block attempts to access old API versions
#
# https://gist.github.com/Firefishy/86ed5b86991b225179b54bbafbcd769e
#
RewriteCond "%{QUERY_STRING}" "^q=abcde&t=20"
- RewriteRule "^/api/0\.6/notes/search$" - [R=204,L]
+ RewriteRule "^/api/0\.6/notes/search$" - [R=429,L]
#
# Force special MIME type for crossdomain.xml files
SetEnv SECRET_KEY_BASE <%= @secret_key_base %>
Alias /favicon.ico <%= node[:web][:base_directory] %>/rails/app/assets/favicons/favicon.ico
Alias /openlayers <%= node[:web][:base_directory] %>/static/openlayers
- Alias /stats /store/rails/stats
- Alias /user/image /store/rails/user/image
- Alias /attachments /store/rails/attachments
+ RedirectPermanent /stats https://planet.openstreetmap.org/statistics
#
# Pass authentication related headers to cgimap
#
# Pass supported calls to cgimap
#
- RewriteRule ^/api/0\.6/map(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
+ RewriteRule ^/api/0\.6/map(\.json|\.xml)?$ unix:/run/cgimap/socket|fcgi://127.0.0.1$0 [P]
RewriteCond %{REQUEST_METHOD} ^(HEAD|GET)$
- RewriteRule ^/api/0\.6/(node|way|relation|changeset)/[0-9]+(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
- RewriteRule ^/api/0\.6/(node|way|relation)/[0-9]+/history(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
- RewriteRule ^/api/0\.6/(node|way|relation)/[0-9]+/relations(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
- RewriteRule ^/api/0\.6/node/[0-9]+/ways(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
- RewriteRule ^/api/0\.6/(way|relation)/[0-9]+/full(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
- RewriteRule ^/api/0\.6/(nodes|ways|relations)(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
- RewriteRule ^/api/0\.6/changeset/[0-9]+/(upload|download)(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
+ RewriteRule ^/api/0\.6/(node|way|relation|changeset)/[0-9]+(\.json|\.xml)?$ unix:/run/cgimap/socket|fcgi://127.0.0.1$0 [P]
+ RewriteRule ^/api/0\.6/(node|way|relation)/[0-9]+/history(\.json|\.xml)?$ unix:/run/cgimap/socket|fcgi://127.0.0.1$0 [P]
+ RewriteRule ^/api/0\.6/(node|way|relation)/[0-9]+/relations(\.json|\.xml)?$ unix:/run/cgimap/socket|fcgi://127.0.0.1$0 [P]
+ RewriteRule ^/api/0\.6/node/[0-9]+/ways(\.json|\.xml)?$ unix:/run/cgimap/socket|fcgi://127.0.0.1$0 [P]
+ RewriteRule ^/api/0\.6/(way|relation)/[0-9]+/full(\.json|\.xml)?$ unix:/run/cgimap/socket|fcgi://127.0.0.1$0 [P]
+ RewriteRule ^/api/0\.6/(nodes|ways|relations)(\.json|\.xml)?$ unix:/run/cgimap/socket|fcgi://127.0.0.1$0 [P]
+ RewriteRule ^/api/0\.6/changeset/[0-9]+/(upload|download)(\.json|\.xml)?$ unix:/run/cgimap/socket|fcgi://127.0.0.1$0 [P]
#
# Redirect trac and wiki requests to the right places
<Directory <%= node[:web][:base_directory] %>/rails/public>
Require all granted
+ RewriteCond "%{HTTP:Accept-encoding}" "br"
+ RewriteCond "%{REQUEST_FILENAME}\.br" -s
+ RewriteRule "^(.*)\.(css|ico|js|json|svg|xml)$" "$1\.$2\.br" [QSA]
+
RewriteCond "%{HTTP:Accept-encoding}" "gzip"
RewriteCond "%{REQUEST_FILENAME}\.gz" -s
RewriteRule "^(.*)\.(css|ico|js|json|svg|xml)$" "$1\.$2\.gz" [QSA]
- RewriteRule "\.css\.gz$" "-" [T=text/css,E=no-gzip:1]
- RewriteRule "\.ico\.gz$" "-" [T=image/vnd.microsoft.icon,E=no-gzip:1]
- RewriteRule "\.js\.gz$" "-" [T=text/javascript,E=no-gzip:1]
- RewriteRule "\.json\.gz$" "-" [T=application/json,E=no-gzip:1]
- RewriteRule "\.svg\.gz$" "-" [T=image/svg+xml,E=no-gzip:1]
- RewriteRule "\.xml\.gz$" "-" [T=application/xml,E=no-gzip:1]
+ RewriteRule "\.css\.(br|gz)$" "-" [T=text/css,E=no-gzip:1,E=no-brotli:1]
+ RewriteRule "\.ico\.(br|gz)$" "-" [T=image/vnd.microsoft.icon,E=no-gzip:1,E=no-brotli:1]
+ RewriteRule "\.js\.(br|gz)$" "-" [T=text/javascript,E=no-gzip:1,E=no-brotli:1]
+ RewriteRule "\.json\.(br|gz)$" "-" [T=application/json,E=no-gzip:1,E=no-brotli:1]
+ RewriteRule "\.svg\.(br|gz)$" "-" [T=image/svg+xml,E=no-gzip:1,E=no-brotli:1]
+ RewriteRule "\.xml\.(br|gz)$" "-" [T=application/xml,E=no-gzip:1,E=no-brotli:1]
+
+ <FilesMatch "\.(css|ico|js|json|svg|xml)\.br$">
+ Header append Content-Encoding br
+ Header append Vary Accept-Encoding
+ </FilesMatch>
<FilesMatch "\.(css|ico|js|json|svg|xml)\.gz$">
Header append Content-Encoding gzip
<Directory /srv/www.openstreetmap.org/rails/vendor/assets>
Require all granted
</Directory>
-
-<Directory /store/rails/stats>
- Require all granted
-</Directory>
-
-<Directory /store/rails/user/image>
- Require all granted
-</Directory>
-
-<Directory /store/rails/attachments>
- Require all granted
-</Directory>
end
end
-parser = ApacheLogRegex.new('%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" %Dus %{UNIQUE_ID}e %{SSL_PROTOCOL}x %{SSL_CIPHER}x')
+parser = ApacheLogRegex.new('%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" %Dus %{UNIQUE_ID}e %{SSL_PROTOCOL}x %{SSL_CIPHER}x %{AUTH_METHOD}e')
last_write = Time.now
statistics = {
:count => Hash.new(0),
:bytes => Hash.new(0),
:seconds => Hash.new(0.0),
- :ssl => Hash.new(0)
+ :ssl => Hash.new(0),
+ :auth => Hash.new(0)
}
File::Tail::Logfile.tail("/var/log/apache2/access.log") do |line|
begin
- hash = parser.parse(line)
+ hash = parser.parse!(line)
uri = categorise_uri(hash["%r"])
status = hash["%>s"]
seconds = hash["%Dus"].to_f / 1000000
protocol = hash["%{SSL_PROTOCOL}x"]
cipher = hash["%{SSL_CIPHER}x"]
+ auth = hash["%{AUTH_METHOD}e"]
statistics[:status][status] += 1
statistics[:uri][uri] += 1
statistics[:bytes][[uri, status]] += bytes
statistics[:seconds][[uri, status]] += seconds
statistics[:ssl][[protocol, cipher]] += 1 unless protocol == "-"
- rescue ApacheLogRegex::ParseError
- # nil
+ statistics[:auth][auth] += 1 unless auth == "-"
+ rescue ApacheLogRegex::ParseError => ex
+ STDERR.puts ex.to_s
end
if Time.now - last_write > 10
file.puts "api_call_ssl_total{protocol=\"#{protocol}\",cipher=\"#{cipher}\"} #{value}"
end
+
+ file.puts "# HELP api_call_auth_method_total Number of calls by authentication method"
+ file.puts "# TYPE api_call_auth_method_total counter"
+
+ statistics[:auth].each do |method, value|
+ file.puts "api_call_auth_method_total{method=\"#{method}\"} #{value}"
+ end
end
File.rename("/var/lib/prometheus/node-exporter/api.tmp", "/var/lib/prometheus/node-exporter/api.prom")
--- /dev/null
+#!/bin/sh
+
+export RAILS_ENV="production"
+export SECRET_KEY_BASE="<%= @secret_key_base %>"
+
+exec /usr/local/bin/passenger-ruby /srv/www.openstreetmap.org/rails/script/deliver-message "$@"
create 0660 rails rails
sharedscripts
postrotate
-<% if File.directory?("#{node[:web][:base_directory]}/rails") -%>
- PASSENGER_INSTANCE_REGISTRY_DIR=<%= node[:passenger][:instance_registry_dir] %> /usr/bin/passenger-config restart-app --ignore-app-not-running <%= node[:web][:base_directory] %>/rails > /dev/null
+<% if node[:recipes].include?("web::rails") -%>
+ /bin/sleep 30
+ PASSENGER_INSTANCE_REGISTRY_DIR=<%= node[:passenger][:instance_registry_dir] %> /usr/bin/passenger-config restart-app --ignore-app-not-running --name rails > /dev/null
<% end -%>
-<% if File.directory?("#{node[:web][:base_directory]}/gpx-import") -%>
- /bin/systemctl try-reload-or-restart gpx-import
+<% if node[:recipes].include?("web::frontend") -%>
+ /bin/systemctl try-reload-or-restart rails-jobs@mailers
+ /bin/systemctl try-reload-or-restart rails-jobs@storage
+ /bin/systemctl try-reload-or-restart rails-jobs@traces
<% end -%>
-<% if File.directory?("#{node[:web][:base_directory]}/cgimap") -%>
+<% if node[:recipes].include?("web::cgimap") -%>
/bin/systemctl reload cgimap
/usr/bin/rsync --preallocate <%= node[:web][:log_directory] %>/cgimap.log.2.gz ironbelly::logs/www.openstreetmap.org/cgimap-<%= node[:hostname] %>-`date -d "-2 days" +%Y-%m-%d`.gz
<% end -%>
+++ /dev/null
-#!/bin/sh
-
-# Get a list of rack processes that are running
-pgrep -u rails -f Rack | sort > /tmp/rails.actual.$$
-
-# Get a list of rack processes we expect to be running
-PASSENGER_INSTANCE_REGISTRY_DIR=<%= node[:passenger][:instance_registry_dir] %> passenger-status | awk '/PID:/ { print $3 }' | sort > /tmp/rails.expected.$$
-
-# Get a list of unexpected rack processes
-pids=$(comm -23 /tmp/rails.actual.$$ /tmp/rails.expected.$$)
-
-# Kill any expected rack processes
-[ -n "$pids" ] && kill -9 $pids > /dev/null 2>&1
-
-# Remove our temporary files
-rm -f /tmp/rails.actual.$$ /tmp/rails.expected.$$
<%= @ruby %> -W0 <%= @directory %>/script/statistics > <%= @directory %>/tmp/data_stats.html
# Move new statistics into place
-mv -f <%= @directory %>/tmp/data_stats.html /store/rails/stats
+rsync --quiet <%= @directory %>/tmp/data_stats.html planet.openstreetmap.org::statistics
# Mail statistics to Blackadder
-mail -s "OpenStreetMap Statistics" blackadderajr@gmail.com < /store/rails/stats/data_stats.html
+mail -s "OpenStreetMap Statistics" blackadderajr@gmail.com < <%= @directory %>/tmp/data_stats.html
version "1.0.0"
supports "ubuntu"
depends "mediawiki"
+depends "systemd"
mediawiki_site "wiki.openstreetmap.org" do
aliases ["wiki.osm.org", "wiki.openstreetmap.com", "wiki.openstreetmap.net",
"wiki.openstreetmap.ca", "wiki.openstreetmap.eu",
- "wiki.openstreetmap.pro", "wiki.openstreetmaps.org"]
- directory "/srv/wiki.openstreetmap.org"
+ "wiki.openstreetmap.pro", "wiki.openstreetmaps.org",
+ "osm.wiki", "www.osm.wiki", "wiki.osm.wiki"]
- fpm_max_children 50
- fpm_start_servers 10
- fpm_min_spare_servers 10
- fpm_max_spare_servers 20
+ fpm_max_children 200
+ fpm_start_servers 25
+ fpm_min_spare_servers 25
+ fpm_max_spare_servers 50
fpm_prometheus_port 9253
database_name "wiki"
metanamespace "Wiki"
- recaptcha_public_key "6LdFIQATAAAAAMwtHeI8KDgPqvRbXeNYSq1gujKz"
- recaptcha_private_key passwords["recaptcha"]
+ hcaptcha_public_key "b67a410b-955e-4049-b432-f9c00e0202c0"
+ hcaptcha_private_key passwords["hcaptcha"]
# site_notice "MAINTENANCE: WIKI READ-ONLY UNTIL Monday 16 May 2016 - 11:00am UTC/GMT."
# site_readonly "MAINTENANCE: WIKI READ-ONLY UNTIL Monday 16 May 2016 - 11:00am UTC/GMT."
template "mw-ext-MultiMaps.inc.php.erb"
template_cookbook "wiki"
variables :thunderforest_key => passwords["thunderforest"]
+ action :delete
+end
+
+mediawiki_extension "JsonConfig" do
+ site "wiki.openstreetmap.org"
+ template "mw-ext-JsonConfig.inc.php.erb"
+ template_cookbook "wiki"
+end
+
+mediawiki_extension "Kartographer" do
+ site "wiki.openstreetmap.org"
+ template "mw-ext-Kartographer.inc.php.erb"
+ template_cookbook "wiki"
end
cookbook_file "/srv/wiki.openstreetmap.org/osm_logo_wiki.png" do
mode "0775"
end
-cron_d "wiki-dump" do
- minute "0"
- hour "2"
+systemd_service "wiki-dump" do
+ description "Wiki dump"
+ type "oneshot"
+ exec_start "/usr/bin/php w/maintenance/dumpBackup.php --full --quiet --output=gzip:dump/dump.xml.gz"
+ working_directory "/srv/wiki.openstreetmap.org"
user "wiki"
- command "cd /srv/wiki.openstreetmap.org && php w/maintenance/dumpBackup.php --full --quiet --output=gzip:dump/dump.xml.gz"
+ sandbox :enable_network => true
+ memory_deny_write_execute false
+ restrict_address_families "AF_UNIX"
+ read_write_paths "/srv/wiki.openstreetmap.org/dump"
+end
+
+systemd_timer "wiki-dump" do
+ description "Wiki dump"
+ on_calendar "02:00"
+end
+
+service "wiki-dump.timer" do
+ action [:enable, :start]
+end
+
+systemd_service "wiki-rdf-dump" do
+ description "Wiki RDF dump"
+ type "oneshot"
+ exec_start [
+ "/usr/bin/php w/extensions/Wikibase/repo/maintenance/dumpRdf.php --wiki wiki --format ttl --flavor full-dump --entity-type item --entity-type property --no-cache --output /tmp/wikibase-rdf.ttl",
+ "/bin/gzip -9 /tmp/wikibase-rdf.ttl",
+ "/bin/mv /tmp/wikibase-rdf.ttl.gz /srv/wiki.openstreetmap.org/dump/wikibase-rdf.ttl.gz"
+ ]
+ working_directory "/srv/wiki.openstreetmap.org"
+ user "wiki"
+ sandbox :enable_network => true
+ memory_deny_write_execute false
+ restrict_address_families "AF_UNIX"
+ read_write_paths "/srv/wiki.openstreetmap.org/dump"
+end
+
+systemd_timer "wiki-rdf-dump" do
+ description "Wiki RDF dump"
+ on_calendar "04:00"
+end
+
+service "wiki-rdf-dump.timer" do
+ action [:enable, :start]
end
--- /dev/null
+<?php
+# DO NOT EDIT - This file is being maintained by Chef
+
+# JsonConfig is a requirement for Kartographer extension
+wfLoadExtension( 'JsonConfig' );
+
--- /dev/null
+<?php
+# DO NOT EDIT - This file is being maintained by Chef
+
+wfLoadExtension( 'Kartographer' );
+$wgKartographerMapServer = 'https://tile.openstreetmap.org';
+$wgKartographerSrcsetScales = [];
+$wgKartographerDfltStyle = '';
+$wgKartographerStyles = [];
+$wgKartographerSimpleStyleMarkers = false;
+++ /dev/null
-<?php
-# DO NOT EDIT - This file is being maintained by Chef
-
-require_once "$IP/extensions/MultiMaps/MultiMaps.php";
-
-# Array of String. Array containing all the mapping services that will be made available to the user.
-# First value - default service, which will be used if the service is not in the parameters
-# Values may be a valid name of class based on class BaseMapService or some string and an array if they
-# denote different tiles within a BaseMapService
-$egMultiMaps_MapServices = [
- 'Leaflet',
- 'cyclosm' => [
- 'service' => 'Leaflet',
- 'attribution' => '© <a href="https://osm.org/copyright">OpenStreetMap contributors</a>. Tiles style by <a href="https://www.cyclosm.org/" target="_blank">CyclOSM</a> hosted by <a href="https://openstreetmap.fr/" target="_blank">OpenStreetMap France</a>',
- 'source' => 'https://{s}.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png',
- ],
- 'cycle' => [
- 'service' => 'Leaflet',
- 'attribution' => '© <a href="https://osm.org/copyright">OpenStreetMap contributors</a>. Tiles courtesy of <a href="https://www.thunderforest.com/" target="_blank">Andy Allan</a>',
- 'source' => 'https://tile.thunderforest.com/cycle/{z}/{x}/{y}.png?apikey=<%= @thunderforest_key %>',
- ],
- 'transport' => [
- 'service' => 'Leaflet',
- 'attribution' => '© <a href="https://osm.org/copyright">OpenStreetMap contributors</a>. Tiles courtesy of <a href="https://www.thunderforest.com/" target="_blank">Andy Allan</a>',
- 'source' => 'https://tile.thunderforest.com/transport/{z}/{x}/{y}.png?apikey=<%= @thunderforest_key %>',
- ],
- 'oepnv' => [
- 'service' => 'Leaflet',
- 'attribution' => '© <a href="https://osm.org/copyright">OpenStreetMap contributors</a>. Tiles courtesy of <a href="https://memomaps.de/" target="_blank">MeMoMaps</a>',
- 'source' => 'https://tileserver.memomaps.de/tilegen/{z}/{x}/{y}.png',
- ],
- 'humanitarian' => [
- 'service' => 'Leaflet',
- 'attribution' => '© <a href="https://osm.org/copyright">OpenStreetMap contributors</a>. Tiles style by <a href="https://www.hotosm.org/" target="_blank">Humanitarian OpenStreetMap team</a> hosted by <a href="https://openstreetmap.fr/" target="_blank">OpenStreetMap France</a>',
- 'source' => 'https://tile.openstreetmap.fr/hot/{z}/{x}/{y}.png'
- ],
-];
<?php
# DO NOT EDIT - This file is being maintained by Chef
+use MediaWiki\MediaWikiServices;
+use Wikibase\Lib\SettingsArray;
+
$wgEnableWikibaseRepo = true;
$wgEnableWikibaseClient = true;
-require_once "$IP/extensions/Wikibase/repo/Wikibase.php";
-require_once "$IP/extensions/Wikibase/client/WikibaseClient.php";
+wfLoadExtension( 'WikibaseRepository', "$IP/extensions/Wikibase/extension-repo.json" );
+wfLoadExtension( 'WikibaseClient', "$IP/extensions/Wikibase/extension-client.json" );
// Include Wikibase.searchindex.php to include string and text values in the full text index:
require_once "$IP/extensions/Wikibase/repo/config/Wikibase.searchindex.php";
$wgNamespacesToBeSearchedDefault,
$wgWBRepoSettings;
- $wgContentHandlerUseDB = true;
-
$baseNs = 120;
// Define custom namespaces. Use these exact constant names.
$wgExtraNamespaces[WB_NS_PROPERTY] = 'Property';
$wgExtraNamespaces[WB_NS_PROPERTY_TALK] = 'Property_talk';
- // Tell Wikibase which namespace to use for which kind of entity
- $wgWBRepoSettings['entityNamespaces']['item'] = WB_NS_ITEM;
- $wgWBRepoSettings['entityNamespaces']['property'] = WB_NS_PROPERTY;
+ $wgWBRepoSettings['entitySources'] = function ( SettingsArray $settings ) {
+ global $wgServer;
+
+ $entityNamespaces = [
+ 'item' => WB_NS_ITEM,
+ 'property' => WB_NS_PROPERTY,
+ ];
+
+ $hookContainer = MediaWikiServices::getInstance()->getHookContainer();
+ $hookContainer->run( 'WikibaseRepoEntityNamespaces', [ &$entityNamespaces ] );
+
+ return [
+ $settings->getSetting( 'localEntitySourceName' ) => [
+ 'entityNamespaces' => $entityNamespaces,
+ 'repoDatabase' => false,
+ 'baseUri' => $wgServer . '/entity/',
+ 'rdfNodeNamespacePrefix' => 'wd',
+ 'rdfPredicateNamespacePrefix' => '',
+ 'interwikiPrefix' => '',
+ ],
+ ];
+ };
// Make sure we use the same keys on repo and clients, so we can share cached objects.
- $wgWBRepoSettings['sharedCacheKeyPrefix'] = $wgDBname;
+ $wgWBRepoSettings['sharedCacheKeyPrefix'] = $wgDBname . ':WBL';
+ $wgWBRepoSettings['sharedCacheKeyGroup'] = $wgDBname;
// Include Wikibase items in the regular search result by default
$wgNamespacesToBeSearchedDefault[WB_NS_ITEM] = true;
} );
-// Adapted from "$IP/extensions/Wikibase/client/ExampleSettings.php";
+// Adapted from "$IP/extensions/Wikibase/client/config/WikibaseClient.example.php";
// The global site ID by which this wiki is known on the repo.
// Defaults to $wgDBname.
// $wgWBClientSettings['siteGlobalID'] = "osm";
-// $wgWBClientSettings['injectRecentChanges'] = true;
-// $wgWBClientSettings['showExternalRecentChanges'] = true;
+
+$wgWBClientSettings['injectRecentChanges'] = true;
+$wgWBClientSettings['showExternalRecentChanges'] = true;
+
+// Base URL for building links to the repository.
+// Assumes your wiki is setup as "http://repo.example.org/wiki/"
+// This can be protocol relative, such as "//www.wikidata.org"
+$wgWBClientSettings['repoUrl'] = "https://wiki.openstreetmap.org";
+
+// This setting is optional if you have the same type of setup for your
+// repo and client. It will default to using the client's $wgArticlePath setting,
+// and if you do not have $wgArticlePath set anywhere, MediaWiki has a default for it.
+$wgWBClientSettings['repoArticlePath'] = "/wiki/$1";
+
+// Assuming your wiki is setup with such script path as "http://repo.example.org/w/api.php". This
+// should be the same as the $wgScriptPath setting if you have it set in your repo. If $wgScriptPath
+// is not set, then MediaWiki assumes a default.
+//
+// If your client and repo are setup in the same way, then the below setting is optional and will
+// default to what you have $wgScriptPath set in the client.
+$wgWBClientSettings['repoScriptPath'] = "/w";
+
+// Tell the client which namespace ID on the repo holds which type of entity.
+$baseRepoNs = 120;
+
+define( 'WB_REPO_NS_ITEM', $baseRepoNs );
+define( 'WB_REPO_NS_PROPERTY', $baseRepoNs + 2 );
+
+$wgWBClientSettings['entitySources'] = [
+ 'local' => [
+ 'repoDatabase' => $wgDBname,
+ 'baseUri' => $wgWBClientSettings['repoUrl'] . '/entity',
+ 'entityNamespaces' => [
+ 'item' => WB_REPO_NS_ITEM,
+ 'property' => WB_REPO_NS_PROPERTY
+ ],
+ 'rdfNodeNamespacePrefix' => 'wd',
+ 'rdfPredicateNamespacePrefix' => '',
+ 'interwikiPrefix' => '',
+ ],
+];
$wgWBClientSettings['namespaces'] = [ NS_MAIN ];
+$wgWBClientSettings['repoSiteName'] = 'Data Items';
// Avoid complaints that nobody seems to know the cause off...
$wgWBClientSettings['entityUsagePerPageLimit'] = 500;
User-agent: Exabot
Crawl-delay: 60
+User-Agent: ImagesiftBot
+Crawl-delay: 60
+
+User-agent: SemrushBot
+Crawl-delay: 60
+
+User-agent: SeznamBot
+Crawl-delay: 60
+
Sitemap: https://wiki.openstreetmap.org/sitemap-index-wiki.xml
Host: wiki.openstreetmap.org
+++ /dev/null
-acl osmwiki_sites dstdomain wiki.openstreetmap.org wiki.osm.org
-
-http_access allow osmwiki_sites
-
-cache_peer localhost parent 80 0 no-query originserver name=osmwikiAccel login=PASS connect-timeout=60 no-digest weight=1000
-
-cache_peer_access osmwikiAccel allow osmtile_sites
-cache_peer_access osmwikiAccel deny all
-
-#----------------------------------
-
require "addressable"
require "httpclient"
-require "php_serialize"
+require "json"
class Chef
module Wordpress
extend Chef::Mixin::ShellOut
@api_responses = {}
- @svn_responses = {}
class << self
def current_version
end
def current_plugin_version(name)
- if svn_cat("https://plugins.svn.wordpress.org/#{name}/trunk/readme.txt") =~ /Stable tag:\s*([^\s\r]*)[\s\r]*/
- Regexp.last_match[1]
- else
- "trunk"
- end
+ plugin_information(name)["version"]
end
private
def core_version_check
- api_get("https://api.wordpress.org/core/version-check/1.6")
+ api_get("https://api.wordpress.org/core/version-check/1.7")
end
- def api_get(url)
- @api_responses[url] ||= ::PHP.unserialize(::HTTPClient.new.get_content(url))
+ def plugin_information(name)
+ api_get("https://api.wordpress.org/plugins/info/1.2/?action=plugin_information&request[slug]=#{name}")
end
- def svn_cat(url)
- unless @svn_responses[url]
- result = shell_out!("svn", "cat", url)
-
- @svn_responses[url] = result.stdout.force_encoding("UTF-8")
- end
-
- @svn_responses[url]
+ def api_get(url)
+ @api_responses[url] ||= ::JSON.parse(::HTTPClient.new.get_content(url))
end
end
end
depends "php"
depends "ssl"
gem "httpclient"
-gem "php_serialize"
package %w[
subversion
+ php-mbstring
php-mysql
+ php-igbinary
+ php-imagick
+ php-intl
+ php-xml
]
apache_module "proxy"
ports [80, 443]
maxretry 6
end
+
+directory "/opt/wp-cli" do
+ owner "root"
+ group "root"
+ mode "755"
+end
+
+remote_file "/opt/wp-cli/wp" do
+ source "https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar"
+ owner "root"
+ group "root"
+ mode "755"
+end
action :sync
repository plugin_repository
revision new_resource.revision
- depth 1
user node[:wordpress][:user]
group node[:wordpress][:group]
end
end
end
end
+
+ execute "wp-cli plugin activate #{new_resource.plugin}" do
+ command "/opt/wp-cli/wp --path='#{site_directory}' plugin activate '#{new_resource.plugin}'"
+ user "www-data"
+ group "www-data"
+ not_if "/opt/wp-cli/wp --path='#{site_directory}' plugin is-active '#{new_resource.plugin}'"
+ ignore_failure plugin_repository.start_with?("https://plugins.svn.wordpress.org/")
+ end
end
action :delete do
+ execute "wp-cli plugin deactivate #{new_resource.plugin}" do
+ command "/opt/wp-cli/wp --path='#{site_directory}' plugin deactivate '#{new_resource.plugin}'"
+ user "www-data"
+ group "www-data"
+ only_if "/opt/wp-cli/wp --path='#{site_directory}' plugin is-active '#{new_resource.plugin}'"
+ end
+
directory plugin_directory do
action :delete
recursive true
property :site, :kind_of => String, :name_property => true
property :aliases, :kind_of => [String, Array]
+property :title, :kind_of => String
+property :admin_user, :kind_of => String, :default => "osm_admin"
+property :admin_email, :kind_of => String, :default => "admins@openstreetmap.org"
property :directory, :kind_of => String
property :version, :kind_of => String
property :database_name, :kind_of => String, :required => true
property :database_user, :kind_of => String, :required => [:create]
property :database_password, :kind_of => String, :required => [:create]
property :database_prefix, :kind_of => String, :default => "wp_"
+property :wp2fa_encrypt_key, :kind_of => String, :required => true
property :urls, :kind_of => Hash, :default => {}
property :fpm_max_children, :kind_of => Integer, :default => 10
property :fpm_start_servers, :kind_of => Integer, :default => 4
line.gsub!(/('LOGGED_IN_SALT', *)'put your unique phrase here'/, "\\1'#{logged_in_salt}'")
line.gsub!(/('NONCE_SALT', *)'put your unique phrase here'/, "\\1'#{nonce_salt}'")
- if line =~ /define\('WP_DEBUG'/
- line += "\n"
- line += "/**\n"
- line += " * Don't allow file editing.\n"
- line += " */\n"
- line += "define('DISALLOW_FILE_EDIT', true);\n"
- line += "define('FORCE_SSL_LOGIN', true);\n"
- line += "define('FORCE_SSL_ADMIN', true);\n"
+ if line =~ /Add any custom values between this line/
+ line += "\r\n"
+ line += "/**\r\n"
+ line += " * Don't allow file editing.\r\n"
+ line += " */\r\n"
+ line += "define( 'WP_HOME', 'https://#{new_resource.site}');\r\n"
+ line += "define( 'WP_SITEURL', 'https://#{new_resource.site}');\r\n"
+ line += "define( 'DISALLOW_FILE_EDIT', true);\r\n"
+ line += "define( 'DISALLOW_FILE_MODS', true);\r\n"
+ line += "define( 'AUTOMATIC_UPDATER_DISABLED', true);\r\n"
+ line += "define( 'FORCE_SSL_LOGIN', true);\r\n"
+ line += "define( 'FORCE_SSL_ADMIN', true);\r\n"
+ line += "define( 'WP_FAIL2BAN_SITE_HEALTH_SKIP_FILTERS', true);\r\n"
+ line += "define( 'WP_ENVIRONMENT_TYPE', 'production');\r\n"
+ line += "define( 'WP_MEMORY_LIMIT', '128M');\r\n"
+ line += "define( 'WP2FA_ENCRYPT_KEY', '#{new_resource.wp2fa_encrypt_key}');\r\n"
end
line
backup false
end
+ # Setup wordpress database and create admin user with random password
+ execute "wp core install" do
+ command "/opt/wp-cli/wp --path='#{site_directory}' core install --url='#{new_resource.site}' --title='#{new_resource.title}' --admin_user='#{new_resource.admin_user}' --admin_email='#{new_resource.admin_email}' --skip-email"
+ user "www-data"
+ group "www-data"
+ only_if { ::File.exist?("#{site_directory}/wp-config.php") }
+ not_if "/opt/wp-cli/wp --path='#{site_directory}' core is-installed"
+ end
+
+ execute "wp core update-db" do
+ command "/opt/wp-cli/wp --path='#{site_directory}' core update-db"
+ user "www-data"
+ group "www-data"
+ only_if { ::File.exist?("#{site_directory}/wp-config.php") }
+ subscribes :run, "subversion[#{site_directory}]"
+ end
+
ssl_certificate new_resource.site do
domains [new_resource.site] + Array(new_resource.aliases)
end
php_admin_values "open_basedir" => "#{site_directory}/:/usr/share/php/:/tmp/",
"disable_functions" => "exec,shell_exec,system,passthru,popen,proc_open"
php_values "upload_max_filesize" => "70M",
- "post_max_size" => "100M"
+ "post_max_size" => "100M",
+ "memory_limit" => "368M"
prometheus_port new_resource.fpm_prometheus_port
end
reload_apache false
end
- http_request "https://#{new_resource.site}/wp-admin/upgrade.php" do
- action :nothing
- url "https://#{new_resource.site}/wp-admin/upgrade.php?step=1"
- subscribes :get, "subversion[#{site_directory}]"
+ wordpress_plugin "wp-fail2ban" do
+ site new_resource.site
+ reload_apache false
end
- wordpress_plugin "wp-fail2ban" do
+ wordpress_plugin "wp-2fa" do
site new_resource.site
reload_apache false
end
- script "#{site_directory}/wp-content/plugins/wp-fail2ban" do
- action :nothing
- interpreter "php"
- cwd site_directory
- user "wordpress"
- code <<-WP_FAIL2BAN
- <?php
- @include "wp-config.php";
- @include_once "wp-includes/functions.php";
- @include_once "wp-admin/includes/plugin.php";
- activate_plugin("wp-fail2ban/wp-fail2ban.php", '', false, false);
- ?>
- WP_FAIL2BAN
- subscribes :run, "wordpress_plugin[wp-fail2ban]"
+ wordpress_plugin "wp-last-login" do
+ site new_resource.site
+ reload_apache false
end
end
action :delete do
+ wordpress_plugin "wp-last-login" do
+ action :delete
+ site new_resource.site
+ reload_apache false
+ end
+
+ wordpress_plugin "wp-2fa" do
+ action :delete
+ site new_resource.site
+ reload_apache false
+ end
+
wordpress_plugin "wp-fail2ban" do
action :delete
site new_resource.site
end
action_class do
- include Chef::Mixin::EditFile
- include Chef::Mixin::PersistentToken
+ include OpenStreetMap::Mixin::EditFile
+ include OpenStreetMap::Mixin::PersistentToken
def site_directory
new_resource.directory || "/srv/#{new_resource.site}"
action :sync
repository theme_repository
revision new_resource.revision
- depth 1
user node[:wordpress][:user]
group node[:wordpress][:group]
end
+ elsif theme_repository.end_with?(".zip")
+ zip_path = "#{Chef::Config[:file_cache_path]}/#{new_resource.theme}.zip"
+
+ remote_file zip_path do
+ source theme_repository
+ action :create
+ end
+
+ archive_file zip_path do
+ destination theme_directory
+ action :nothing
+ overwrite true
+ group node[:wordpress][:group]
+ owner node[:wordpress][:user]
+ subscribes :extract, "remote_file[#{zip_path}]", :immediately
+ end
else
subversion theme_directory do
action :sync
ServerAdmin webmaster@openstreetmap.org
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
RedirectPermanent / https://<%= @name %>/
</VirtualHost>
+<% unless @aliases.empty? -%>
<VirtualHost *:443>
- ServerName <%= @name %>
-<% @aliases.each do |alias_name| -%>
+ ServerName <%= @aliases.first %>
+<% @aliases.drop(1).each do |alias_name| -%>
ServerAlias <%= alias_name %>
+<% end -%>
ServerAdmin webmaster@openstreetmap.org
SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
- CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
ErrorLog /var/log/apache2/<%= @name %>-error.log
+
+ RedirectPermanent / https://<%= @name %>/
+</VirtualHost>
<% end -%>
+<VirtualHost *:443>
+ ServerName <%= @name %>
+
+ ServerAdmin webmaster@openstreetmap.org
+
+ SSLEngine on
+ SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
+ SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
+
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined_extended
+ ErrorLog /var/log/apache2/<%= @name %>-error.log
+
DocumentRoot <%= @directory %>
<% @urls.each do |url,directory| -%>
Alias <%= url %> <%= directory %>
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
RewriteRule ^wp-includes/theme-compat/ - [F,L]
RewriteRule ^readme\.html$ [F,L]
+ RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
Require all granted
+ # https://www.wp-pay.org/http-authorization-header-missing/
+ CGIPassAuth on
+
<FilesMatch ".+\.ph(ar|p|tml)$">
- SetHandler "proxy:unix:/run/php/<%= @name %>.sock|fcgi://127.0.0.1"
+ SetHandler "proxy:unix:/run/php/php-<%= @name %>-fpm.sock|fcgi://127.0.0.1"
</FilesMatch>
</Directory>
Require all denied
</Directory>
- <Files ~ "\.(txt|md)$">
+ <Files ~ "(?<!robots|ads|security|humans)\.(txt|md)$">
Require all denied
</Files>
<Files ~ "~$">
Require all denied
</Files>
+
+ <Files "xmlrpc.php">
+ Require all denied
+ </Files>
</VirtualHost>
-#!/usr/bin/ruby
+#!/usr/bin/env ruby
ok = true
file =~ /\.rb$/ || (file !~ /\.erb$/ && %x(file --brief --mime-type #{file}) == "text/x-ruby\n")
end
- ok &&= system("bundle", "exec", "rubocop", *ruby_files) unless ruby_files.empty?
-
- cookbooks = files.grep(%r{(cookbooks/[^/]+)/}) { Regexp.last_match(1) }.uniq
-
- ok &&= system("bundle", "exec", "foodcritic", *cookbooks) unless cookbooks.empty?
+ ok &&= system("bundle", "exec", "cookstyle", *ruby_files) unless ruby_files.empty?
system("git", "stash", "pop", "--quiet") if need_stash
else
default_attributes(
:networking => {
:interfaces => {
- :external_ipv4 => {
+ :external => {
:interface => "enp1s0f0",
:role => :external,
- :family => :inet,
- :address => "51.159.53.238",
- :prefix => "24",
- :gateway => "51.159.53.1"
- },
- :external_ipv6 => {
- :interface => "enp1s0f0",
- :role => :external,
- :family => :inet6,
- :address => "2001:bc8:1200:4:dac4:97ff:fe8a:9cfc",
- :prefix => "64",
- :gateway => "fe80::a293:51ff:fea2:ded5"
- }
- }
- },
- :postgresql => {
- :settings => {
- :defaults => {
- :shared_buffers => "8GB",
- :maintenance_work_mem => "7144MB",
- :effective_cache_size => "16GB"
- }
- }
- },
- :sysctl => {
- :postgres => {
- :comment => "Increase shared memory for postgres",
- :parameters => {
- "kernel.shmmax" => 9 * 1024 * 1024 * 1024,
- "kernel.shmall" => 9 * 1024 * 1024 * 1024 / 4096
- }
- }
- },
- :tile => {
- :database => {
- :cluster => "12/main",
- :postgis => "3"
- },
- :styles => {
- :default => {
- :tile_directories => [
- { :name => "/store/tiles/default", :min_zoom => 0, :max_zoom => 19 }
- ]
+ :inet => {
+ :address => "51.159.53.238",
+ :prefix => "24",
+ :gateway => "51.159.53.1"
+ },
+ :inet6 => {
+ :address => "2001:bc8:1200:4:dac4:97ff:fe8a:9cfc",
+ :prefix => "64",
+ :gateway => "fe80::a293:51ff:fea2:ded5"
+ }
}
}
}
)
run_list(
- "role[scaleway]",
- "role[tile]"
+ "role[scaleway]"
)
+++ /dev/null
-name "altavoz"
-description "Role applied to all servers at AltaVoz"
-
-default_attributes(
- :hosted_by => "AltaVoz",
- :location => "Viña del Mar, Chile"
-)
-
-override_attributes(
- :networking => {
- :nameservers => ["200.91.44.10", "200.91.41.10"]
- },
- :ntp => {
- :servers => ["0.cl.pool.ntp.org", "1.cl.pool.ntp.org", "south-america.pool.ntp.org"]
- }
-)
-
-run_list(
- "role[cl]"
-)
description "Master role applied to angor"
default_attributes(
- :hardware => {
- :shm_size => "18g"
- },
:networking => {
:interfaces => {
- :external_ipv4 => {
- :interface => "eno1",
- :role => :external,
- :family => :inet,
- :address => "196.10.54.165",
- :prefix => "29",
- :gateway => "196.10.54.161"
- },
- :external_ipv6 => {
+ :external => {
:interface => "eno1",
:role => :external,
- :family => :inet6,
- :address => "2001:43f8:1f4:b00:b283:feff:fed8:dd45",
- :prefix => "64",
- :gateway => "2001:43f8:1f4:b00::1"
+ :inet => {
+ :address => "196.10.54.165",
+ :prefix => "29",
+ :gateway => "196.10.54.161"
+ },
+ :inet6 => {
+ :address => "2001:43f8:1f4:b00:b283:feff:fed8:dd45",
+ :prefix => "64",
+ :gateway => "2001:43f8:1f4:b00::1"
+ }
}
}
},
- :squid => {
- :version => 4,
- :cache_mem => "16384 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 12800 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 16000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 22400 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 22800 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :tilecache => {
- :tile_parent => "capetown.render.openstreetmap.org"
+ :accounts => {
+ :users => {
+ :htonl => { :status => :user },
+ :gmoncrieff => { :status => :user },
+ :zander => { :status => :user },
+ :"za-imagery" => {
+ :status => :role,
+ :members => [:grant, :htonl, :gmoncrieff, :zander]
+ }
+ }
}
)
run_list(
- "role[inxza]",
- "role[tilecache]",
- "role[ftp]"
+ "role[inxza]"
)
description "Master role applied to ascalon"
default_attributes(
- :hardware => {
- :shm_size => "20g"
- },
:networking => {
:interfaces => {
- :external_ipv4 => {
+ :external => {
:interface => "eno1",
:role => :external,
- :family => :inet,
- :address => "184.107.48.228",
- :prefix => "27",
- :gateway => "184.107.48.225"
+ :inet => {
+ :address => "184.107.48.228",
+ :prefix => "27",
+ :gateway => "184.107.48.225"
+ }
}
}
- },
- :squid => {
- :version => 4,
- :cache_mem => "16384 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :tilecache => {
- :tile_parent => "montreal.render.openstreetmap.org"
}
)
run_list(
- "role[netalerts]",
- "role[tilecache]"
+ "role[netalerts]"
)
--- /dev/null
+name "aws-us-east-2"
+description "Role applied to all servers at AWS us-east-2"
+
+default_attributes(
+ :location => "Ohio",
+ :timezone => "US/Eastern"
+)
+
+run_list(
+ "role[us]",
+ "role[aws]"
+)
--- /dev/null
+name "aws"
+description "Role applied to all servers at AWS"
+
+default_attributes(
+ :hosted_by => "AWS"
+)
+
+override_attributes(
+ :ntp => {
+ :servers => ["169.254.169.123"]
+ }
+)
:transfer_logging => false,
:hosts_allow => [
"193.60.236.0/24", # ucl external
- "10.0.48.0/20", # equinix internal
- "130.117.76.0/27", # equinix external
- "2001:978:2:2C::172:0/112", # equinix external
+ "10.0.48.0/20", # amsterdam internal
+ "184.104.179.128/27", # amsterdam external
+ "2001:470:1:fa1::/64", # amsterdam external
+ "10.0.64.0/20", # dublin internal
+ "184.104.226.96/27", # dublin external
+ "2001:470:1:b3b::/64", # dublin external
"10.0.32.0/20", # bytemark internal
"89.16.162.16/28", # bytemark external
"2001:41c9:2:d6::/64", # bytemark external
default_attributes(
:networking => {
:interfaces => {
- :external_ipv4 => {
+ :external => {
:interface => "bond0",
:role => :external,
- :family => :inet,
- :address => "138.44.68.134",
- :prefix => "30",
- :gateway => "138.44.68.133",
+ :inet => {
+ :address => "138.44.68.134",
+ :prefix => "30",
+ :gateway => "138.44.68.133"
+ },
:bond => {
- :slaves => %w[ens14f0 ens14f1]
+ :slaves => %w[ens14f0np0 ens14f1np1]
}
}
}
:postgresql => {
:settings => {
:defaults => {
- :shared_buffers => "8GB",
- :maintenance_work_mem => "7144MB",
:effective_cache_size => "16GB"
}
}
},
:tile => {
:database => {
- :cluster => "12/main",
+ :cluster => "16/main",
:postgis => "3"
},
+ :mapnik => "3.1",
:styles => {
:default => {
:tile_directories => [
:jburgess => { :status => :administrator }
}
},
- :munin => {
- :plugins => {
- :chrony => {
- :systime => { :warning => "100", :critical => "250" }
- }
- }
- },
:networking => {
:roles => {
- :internal => { :metric => 200, :zone => "loc" },
- :external => { :metric => 100, :zone => "osm" }
+ :internal => { :metric => 200 },
+ :external => { :metric => 100 }
},
:search => ["openstreetmap.org"]
},
+ :prometheus => {
+ :metrics => {
+ :exim_queue_limit => {
+ :help => "Mail queue alert level",
+ :metric => 50
+ }
+ }
+ },
:sysctl => {
:panic => {
:comment => "Reboot automatically after a panic",
}
},
:default_qdisc => {
- :comment => "Use fq as the default queuing discipline and cubic for congestion control",
+ :comment => "Use fq as the default queuing discipline",
:parameters => {
- "net.core.default_qdisc" => "fq",
- "net.ipv4.tcp_congestion_control" => "cubic"
+ "net.core.default_qdisc" => "fq"
}
},
:tune_cpu_scheduler => {
:comment => "Tune CPU scheduler for server scheduling",
:parameters => {
- "kernel.sched_migration_cost_ns" => 50000000,
"kernel.sched_autogroup_enabled" => 0
}
}
"recipe[devices]",
"recipe[hardware]",
"recipe[prometheus]",
- "recipe[munin::plugins]",
"recipe[networking]",
"recipe[exim]",
"recipe[ntp]",
+++ /dev/null
-name "blix-nl"
-description "Role applied to all servers at Blix NL"
-
-default_attributes(
- :location => "Amsterdam, Netherlands"
-)
-
-override_attributes(
- :ntp => {
- :servers => ["0.nl.pool.ntp.org", "1.nl.pool.ntp.org", "europe.pool.ntp.org"]
- }
-)
-
-run_list(
- "role[nl]",
- "role[blix]"
-)
+++ /dev/null
-name "blix-no"
-description "Role applied to all servers at Blix NO"
-
-default_attributes(
- :location => "Oslo, Norway"
-)
-
-override_attributes(
- :ntp => {
- :servers => ["0.no.pool.ntp.org", "1.no.pool.ntp.org", "europe.pool.ntp.org"]
- }
-)
-
-run_list(
- "role[no]",
- "role[blix]"
-)
+++ /dev/null
-name "blix"
-description "Role applied to all servers at Blix"
-
-default_attributes(
- :accounts => {
- :users => {
- :blixadmin => { :status => :administrator }
- }
- },
- :hosted_by => "Blix Solutions"
-)
--- /dev/null
+name "blog-staging"
+description "Role applied to staging blog servers"
+
+default_attributes(
+ :accounts => {
+ :users => {
+ :mikel => { :status => :administrator },
+ :wordpress => {
+ :status => :role,
+ :members => [:mikel]
+ }
+ },
+ }
+)
+
+# FIXME: Disable while site under development
+# run_list(
+# "recipe[blog::staging]"
+# )
--- /dev/null
+name "blogs"
+description "Role applied to all blog aggregators"
+
+run_list(
+ "recipe[blogs]"
+)
+++ /dev/null
-name "boitata"
-description "Master role applied to boitata"
-
-default_attributes(
- :hardware => {
- :shm_size => "14g"
- },
- :networking => {
- :interfaces => {
- :external_ipv4 => {
- :interface => "ens3",
- :role => :external,
- :family => :inet,
- :address => "200.236.31.207",
- :prefix => "25",
- :gateway => "200.236.31.254"
- },
- :external_ipv6 => {
- :interface => "ens3",
- :role => :external,
- :family => :inet6,
- :address => "2801:82:80ff:8002:216:ccff:feaa:21",
- :prefix => "64",
- :gateway => "fe80::92e2:baff:fe0d:e24"
- }
- }
- },
- :squid => {
- :version => 4,
- :cache_mem => "8192 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :tilecache => {
- :tile_parent => "brazil.render.openstreetmap.org"
- }
-)
-
-run_list(
- "role[c3sl]",
- "role[tilecache]"
-)
default_attributes(
:networking => {
:interfaces => {
- :external_ipv4 => {
+ :external => {
:interface => "bond0",
:role => :external,
- :family => :inet,
- :address => "138.44.68.106",
- :prefix => "30",
- :gateway => "138.44.68.105",
+ :inet => {
+ :address => "138.44.68.106",
+ :prefix => "30",
+ :gateway => "138.44.68.105"
+ },
:bond => {
- :slaves => %w[ens14f0 ens14f1]
+ :slaves => %w[ens14f0np0 ens14f1np1]
}
}
}
:postgresql => {
:settings => {
:defaults => {
- :shared_buffers => "8GB",
- :maintenance_work_mem => "7144MB",
:effective_cache_size => "16GB"
}
}
},
:tile => {
:database => {
- :cluster => "12/main",
+ :cluster => "16/main",
:postgis => "3"
},
+ :mapnik => "3.1",
:styles => {
:default => {
:tile_directories => [
}
},
:external => {
- :zone => "bm",
:inet => {
:prefix => "28",
:gateway => "89.16.162.17"
}
}
}
- },
- :web => {
- :backends => %w[rails4 rails5],
- :fileserver => "grisu",
- :readonly_database_host => "katla.bm.openstreetmap.org"
}
)
override_attributes(
:networking => {
- :nameservers => ["10.0.32.20"],
+ :nameservers => ["8.8.8.8", "8.8.4.4"],
:search => ["bm.openstreetmap.org", "openstreetmap.org"]
},
:ntp => {
+++ /dev/null
-name "c3sl"
-description "Role applied to all servers at Centro de Computação CientÃfica e Software Livre"
-
-default_attributes(
- :accounts => {
- :users => {
- :c3sl => { :status => :administrator }
- }
- },
- :hosted_by => "Centro de Computação CientÃfica e Software Livre, Universidade Federal do Paraná",
- :location => "Curitiba, Brazil",
- :networking => {
- :wireguard => { :keepalive => 180 }
- },
- :timezone => "America/Sao_Paulo"
-)
-
-override_attributes(
- :networking => {
- :nameservers => ["200.17.202.3", "200.236.31.1"]
- },
- :ntp => {
- :servers => ["0.br.pool.ntp.org", "1.br.pool.ntp.org", "south-america.pool.ntp.org"]
- }
-)
-
-run_list(
- "role[br]"
-)
name "chef-server"
description "Role applied to all chef servers"
-default_attributes(
- :munin => {
- :plugins => {
- :chef_status => {
- :ascalon => { :warning => ":", :critical => ":" },
- :idris => { :warning => ":", :critical => ":" },
- :norbert => { :warning => ":", :critical => ":" },
- :smaug => { :warning => ":", :critical => ":" },
- :zark => { :warning => ":", :critical => ":" }
- }
- }
- }
-)
-
run_list(
"recipe[chef::server]"
)
+++ /dev/null
-name "cherufe"
-description "Master role applied to cherufe"
-
-default_attributes(
- :hardware => {
- :shm_size => "12g"
- },
- :networking => {
- :interfaces => {
- :external_ipv4 => {
- :interface => "ens18",
- :role => :external,
- :family => :inet,
- :address => "200.91.44.37",
- :prefix => "23",
- :gateway => "200.91.44.1"
- }
- }
- },
- :openssh => {
- :port => 45222
- },
- :squid => {
- :version => 4,
- :cache_mem => "8192 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :nginx => {
- :cache => {
- :proxy => {
- :max_size => "8192M"
- }
- }
- },
- :tilecache => {
- :tile_parent => "vinadelmar.render.openstreetmap.org"
- }
-)
-
-run_list(
- "role[altavoz]",
- "role[tilecache]"
-)
+++ /dev/null
-name "chrysophylax"
-description "Master role applied to chrysophylax"
-
-default_attributes(
- :hardware => {
- :shm_size => "14g"
- },
- :networking => {
- :interfaces => {
- :external_ipv4 => {
- :interface => "ens160",
- :role => :external,
- :family => :inet,
- :address => "217.71.244.22",
- :prefix => "30",
- :gateway => "217.71.244.21"
- },
- :external_ipv6 => {
- :interface => "ens160",
- :role => :external,
- :family => :inet6,
- :address => "2001:8e0:40:2039::10",
- :prefix => "64",
- :gateway => "2001:8e0:40:2039::1"
- }
- }
- },
- :squid => {
- :version => 4,
- :cache_mem => "10240 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :nginx => {
- :cache => {
- :proxy => {
- :max_size => "16384M"
- }
- }
- },
- :tilecache => {
- :tile_parent => "zurich.render.openstreetmap.org"
- }
-)
-
-run_list(
- "role[iway]",
- "role[geodns]",
- "role[tilecache]"
-)
+++ /dev/null
-name "clifford"
-description "Master role applied to clifford"
-
-default_attributes(
- :exim => {
- :rewrites => [
- {
- :pattern => "www-data@openstreetmap.org",
- :replacement => "forum@noreply.openstreetmap.org",
- :flags => "F"
- }
- ]
- },
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "enp2s0f0.2801",
- :role => :internal,
- :family => :inet,
- :address => "10.0.0.17"
- },
- :external_ipv4 => {
- :interface => "enp2s0f0.2800",
- :role => :external,
- :family => :inet,
- :address => "193.60.236.11"
- }
- }
- }
-)
-
-run_list(
- "role[ucl]",
- "role[hp-dl360-g6]",
- "role[forum]"
-)
--- /dev/null
+name "community"
+description "Role applied to all community servers"
+
+default_attributes(
+ :accounts => {
+ :users => {
+ :community => {
+ :status => :role,
+ :members => [:grant, :tomh]
+ }
+ }
+ }
+)
+
+run_list(
+ "recipe[community]"
+)
}
},
:exim => {
- :local_domains => ["join.osmfoundation.org"],
+ :local_domains => ["join.osmfoundation.org", "supporting.openstreetmap.org"],
:routes => {
:join_return => {
:comment => "return@join.osmfoundation.org",
:maildir => "/var/mail/crm-mail",
:user => "www-data",
:group => "mail"
+ },
+ :supporting_return => {
+ :comment => "return@supporting.openstreetmap.org",
+ :domains => ["supporting.osmfoundation.org"],
+ :local_parts => ["return"],
+ :maildir => "/var/mail/crm-return",
+ :user => "www-data",
+ :group => "mail"
+ },
+ :supporting_mail => {
+ :comment => "mail@supporting.openstreetmap.org",
+ :domains => ["supporting.openstreetmap.org"],
+ :local_parts => ["mail"],
+ :maildir => "/var/mail/crm-mail",
+ :user => "www-data",
+ :group => "mail"
}
},
:trusted_users => ["www-data"]
+ },
+ :mysql => {
+ :settings => {
+ :mysqld => {
+ :log_bin_trust_function_creators => 1
+ }
+ }
}
)
--- /dev/null
+name "culebre"
+description "Master role applied to culebre"
+
+default_attributes(
+ :networking => {
+ :interfaces => {
+ :internal => {
+ :interface => "bond0",
+ :role => :internal,
+ :inet => {
+ :address => "10.0.64.9"
+ },
+ :bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
+ :slaves => %w[enp68s0f0 enp68s0f1 enp68s0f2 enp68s0f3]
+ }
+ },
+ :external => {
+ :interface => "bond0.101",
+ :role => :external,
+ :inet => {
+ :address => "184.104.226.105"
+ },
+ :inet6 => {
+ :address => "2001:470:1:b3b::9"
+ }
+ }
+ }
+ },
+ :postgresql => {
+ :settings => {
+ :defaults => {
+ :effective_cache_size => "16GB"
+ }
+ }
+ },
+ :sysctl => {
+ :postgres => {
+ :comment => "Increase shared memory for postgres",
+ :parameters => {
+ "kernel.shmmax" => 9 * 1024 * 1024 * 1024,
+ "kernel.shmall" => 9 * 1024 * 1024 * 1024 / 4096
+ }
+ }
+ },
+ :tile => {
+ :database => {
+ :cluster => "16/main",
+ :postgis => "3"
+ },
+ :mapnik => "3.1",
+ :styles => {
+ :default => {
+ :tile_directories => [
+ { :name => "/store/tiles/default", :min_zoom => 0, :max_zoom => 19 }
+ ]
+ }
+ }
+ }
+)
+
+run_list(
+ "role[equinix-dub]",
+ "role[tile]"
+)
default_attributes(
:postgresql => {
+ :monitor_queries => true,
:settings => {
:defaults => {
- :wal_level => "logical",
:archive_mode => "on",
- :archive_command => "/usr/local/bin/openstreetmap-wal-e --terse wal-push %p",
- :max_wal_senders => "4",
- :max_replication_slots => "1",
- :late_authentication_rules => [
- { :database => "replication", :user => "replication", :address => "10.0.48.49/32" },
- { :database => "replication", :user => "replication", :address => "10.0.48.50/32" },
- { :database => "replication", :user => "replication", :address => "10.0.48.5/32" },
- { :database => "replication", :user => "replication", :address => "10.0.0.4/32" },
- { :database => "replication", :user => "replication", :address => "10.0.0.10/32" },
- { :database => "replication", :user => "replication", :address => "10.0.32.40/32" }
- ]
+ :archive_command => "/usr/local/bin/openstreetmap-wal-g wal-push %p --walg-prevent-wal-overwrite=true",
+ :wal_keep_size => "16384"
}
}
}
:user => "replication",
:passwords => { :bag => "db", :item => "passwords" }
},
- :restore_command => "/usr/local/bin/openstreetmap-wal-e --terse wal-fetch %f %p"
+ :restore_command => "/usr/local/bin/openstreetmap-wal-g wal-fetch %f %p"
}
}
}
:enable => false
}
},
- :munin => {
- :plugins => {
- :postgres_connections_openstreetmap => {
- :waiting => {
- :warning => 10,
- :critical => 20
- }
- },
- :postgres_locks_openstreetmap => {
- :accesssharelock => {
- :warning => 900,
- :critical => 1000
- },
- :rowexclusivelock => {
- :warning => 250,
- :critical => 300
- }
- }
- }
- },
- :nfs => {
- "/store/rails" => { :host => "ironbelly", :path => "/store/rails" }
- },
:postgresql => {
:settings => {
:defaults => {
:listen_addresses => "*",
- :max_connections => "1000",
+ :max_connections => "1500",
:max_stack_depth => "7MB",
- :checkpoint_segments => "32",
+ :wal_level => "logical",
:max_wal_size => "1536MB",
:checkpoint_completion_target => "0.8",
:cpu_tuple_cost => "0.1",
+ :jit => "off",
:log_min_duration_statement => "1000",
:late_authentication_rules => [
- { :address => "10.0.32.0/20" },
- { :address => "10.0.48.0/20" }
+ { :address => "10.0.48.0/20" }, # amsterdam
+ { :address => "10.0.64.0/20" }, # dublin
+ { :database => "replication", :user => "replication", :address => "10.0.0.4/32" }, # snap-02
+ { :database => "replication", :user => "replication", :address => "10.0.0.10/32" }, # eddie
+ { :database => "replication", :user => "replication", :address => "10.0.48.49/32" }, # snap-01
+ { :database => "replication", :user => "replication", :address => "10.0.48.50/32" }, # karm
+ { :database => "replication", :user => "replication", :address => "10.0.64.50/32" } # snap-03
]
}
}
}
}
)
-
-run_list(
- "recipe[nfs]"
-)
default_attributes(
:accounts => {
:users => {
- :edgemaster => { :status => :administrator },
- :emacsen => { :status => :administrator },
- :twain => { :status => :user },
- :bretth => { :status => :user },
- :richard => { :status => :user },
- :shaunmcdonald => { :status => :user },
- :random => { :status => :user },
- :steve8 => { :status => :user },
+ :ant => { :status => :user },
+ :antonkh => { :status => :user },
+ :apmon => { :status => :user },
:blackadder => { :status => :user },
- :timsc => { :status => :user },
:bobkare => { :status => :user },
+ :bretth => { :status => :user },
+ :bsupnik => { :status => :user },
+ :chippy => { :status => :user },
+ :cobra => { :status => :user },
+ :csmale => { :status => :user },
+ :dan => { :status => :user },
:daveh => { :status => :user },
- :gravitystorm => { :status => :user },
- :fred => { :status => :user },
- :nick => { :status => :user },
+ :davidearl => { :status => :user },
:deelkar => { :status => :user },
- :simone => { :status => :user },
- :mitjak => { :status => :user },
+ :derick => { :status => :user },
+ :dmlu => { :status => :user },
+ :dodobas => { :status => :user },
+ :edgemaster => { :status => :administrator },
+ :emacsen => { :status => :user },
+ :enelson => { :status => :user },
+ :fred => { :status => :user },
+ :gmoncrieff => { :status => :user },
+ :gravitystorm => { :status => :user },
+ :gregory => { :status => :user },
+ :gregrs => { :status => :user },
+ :harrywood => { :status => :user },
:htonl => { :status => :user },
- :russ => { :status => :user },
- :merio => { :status => :user },
- :chippy => { :status => :user },
+ :jeslop => { :status => :user },
+ :jfire => { :status => :user },
+ :jgc => { :status => :user },
:joerichards => { :status => :user },
- :pafciu17 => { :status => :user },
- :ojw => { :status => :user },
- :harrywood => { :status => :user },
- :yellowbkpk => { :status => :user },
- :apmon => { :status => :user },
- :mackerski => { :status => :user },
+ :joshd => { :status => :user },
:ldp => { :status => :user },
+ :lfrancke => { :status => :user },
+ :ligfietser => { :status => :user },
+ :lonvia => { :status => :user },
+ :maba => { :status => :user },
+ :mackerski => { :status => :user },
+ :malenki => { :status => :user },
:mdaines => { :status => :user },
- :dan => { :status => :user },
- :ris => { :status => :user },
+ :merio => { :status => :user },
+ :mhohmann => { :status => :user },
+ :milliams => { :status => :user },
+ :mitjak => { :status => :user },
+ :msbarry => { :status => :user },
+ :mvexel => { :status => :user },
+ :nick => { :status => :user },
+ :nicolas17 => { :status => :user },
:nroets => { :status => :user },
+ :ojw => { :status => :user },
:ollie => { :status => :user },
- :mvexel => { :status => :user },
- :tomchance => { :status => :user },
- :lfrancke => { :status => :user },
- :davidearl => { :status => :user },
- :rweait => { :status => :user },
- :ant => { :status => :user },
- :milliams => { :status => :user },
+ :pafciu17 => { :status => :user },
:pierzen => { :status => :user },
- :gregory => { :status => :user },
- :bsupnik => { :status => :user },
- :derick => { :status => :user },
- :joshd => { :status => :user },
- :maba => { :status => :user },
:pnorman => { :status => :user },
- :csmale => { :status => :user },
- :jgc => { :status => :user },
- :cobra => { :status => :user },
:ppawel => { :status => :user },
+ :random => { :status => :user },
+ :richard => { :status => :user },
+ :rtnf => { :status => :user },
+ :ris => { :status => :user },
+ :russ => { :status => :user },
+ :rweait => { :status => :user },
+ :shaunmcdonald => { :status => :user },
:simon04 => { :status => :user },
- :jfire => { :status => :user },
- :malenki => { :status => :user },
- :lonvia => { :status => :user },
- :nicolas17 => { :status => :user },
- :zverik => { :status => :user },
- :dodobas => { :status => :user },
- :mhohmann => { :status => :user },
- :enelson => { :status => :user },
- :gregrs => { :status => :user },
+ :simone => { :status => :user },
:stereo => { :status => :user },
- :dmlu => { :status => :user },
+ :steve8 => { :status => :user },
+ :timsc => { :status => :user },
+ :tomchance => { :status => :user },
+ :twain => { :status => :user },
+ :yellowbkpk => { :status => :user },
+ :zander => { :status => :user },
+ :zverik => { :status => :user },
:ooc => {
:status => :role,
:members => [:tomh, :blackadder, :timsc, :ollie]
:gpsmid => {
:status => :role,
:members => [:apmon, :maba]
+ },
+ :"za-imagery" => {
+ :status => :role,
+ :members => [:grant, :htonl, :gmoncrieff, :zander]
}
}
},
},
:tomh => {
:repository => "https://github.com/tomhughes/openstreetmap-website.git",
- :revision => "next"
+ :revision => "next",
+ :cgimap_repository => "https://github.com/zerebubuth/openstreetmap-cgimap.git",
+ :cgimap_revision => "master"
},
:comments => {
:repository => "https://github.com/ukasiu/openstreetmap-website.git",
:repository => "https://github.com/openbrian/osm-microcosms.git",
:revision => "microcosms"
},
- :upload => {
- :repository => "https://git.openstreetmap.org/public/rails.git",
- :revision => "master",
- :cgimap_repository => "https://github.com/zerebubuth/openstreetmap-cgimap.git",
- :cgimap_revision => "feature/bulk_upload"
- },
- :oauth2 => {
- :repository => "https://github.com/tomhughes/openstreetmap-website.git",
- :revision => "doorkeeper",
- :cgimap_repository => "https://github.com/zerebubuth/openstreetmap-cgimap.git",
- :cgimap_revision => "feature/oauth2"
+ :signup => {
+ :repository => "https://github.com/milan-cvetkovic/openstreetmap-website.git",
+ :revision => "issue_4128_login_signup"
}
}
},
:postgresql => {
- :versions => ["13"],
+ :versions => ["15"],
:settings => {
:defaults => {
:max_connections => "500",
:max_stack_depth => "4MB",
:effective_cache_size => "4GB"
},
- "13" => {
+ "15" => {
:port => "5432",
- :wal_level => "logical",
- :max_replication_slots => "1"
+ :wal_level => "logical"
}
}
},
"kernel.shmmax" => "17179869184"
}
}
+ },
+ :openssh => {
+ :password_authentication => true
}
)
+++ /dev/null
-name "donate"
-description "Role applied to all donate servers"
-
-run_list(
- "recipe[donate]"
-)
+++ /dev/null
-name "draco"
-description "Master role applied to draco"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "enp3s0f0.2801",
- :role => :internal,
- :family => :inet,
- :address => "10.0.0.11"
- },
- :external_ipv4 => {
- :interface => "enp3s0f0.2800",
- :role => :external,
- :family => :inet,
- :address => "193.60.236.12"
- }
- }
- }
-)
-
-run_list(
- "role[ucl]"
-)
--- /dev/null
+name "dribble"
+description "Master role applied to dribble"
+
+default_attributes(
+ :networking => {
+ :interfaces => {
+ :internal => {
+ :interface => "bond0",
+ :role => :internal,
+ :inet => {
+ :address => "10.0.48.4"
+ },
+ :bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
+ :slaves => %w[eno1 eno2 eno3 eno4 eno5 eno6]
+ }
+ },
+ :external => {
+ :interface => "bond0.3",
+ :role => :external,
+ :inet => {
+ :address => "184.104.179.132"
+ },
+ :inet6 => {
+ :address => "2001:470:1:fa1::4"
+ }
+ }
+ }
+ },
+ :accounts => {
+ :users => {
+ :stereo => { :status => :administrator }
+ }
+ }
+)
+
+run_list(
+ "role[equinix-ams]",
+ "role[taginfo]"
+)
+++ /dev/null
-name "drogon"
-description "Master role applied to drogon"
-
-default_attributes(
- :accounts => {
- :users => {
- :zelja => { :status => :administrator }
- }
- },
- :hardware => {
- :shm_size => "18g"
- },
- :location => "Osijek, Croatia",
- :networking => {
- :interfaces => {
- :external_ipv4 => {
- :interface => "eth0",
- :role => :external,
- :family => :inet,
- :address => "161.53.30.107",
- :prefix => "27",
- :gateway => "161.53.30.97"
- },
- :external_ipv6 => {
- :interface => "eth0",
- :role => :external,
- :family => :inet6,
- :address => "2001:b68:c0ff:0:221:5eff:fe40:c7c4",
- :prefix => "64",
- :gateway => "fe80::161:53:30:97"
- }
- }
- },
- :squid => {
- :version => 4,
- :cache_mem => "16384 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :tilecache => {
- :tile_parent => "osijek.render.openstreetmap.org"
- }
-)
-
-run_list(
- "role[carnet]",
- "role[tilecache]"
-)
default_attributes(
:networking => {
:interfaces => {
- :internal_ipv4 => {
+ :internal => {
:interface => "bond0",
:role => :internal,
- :family => :inet,
- :address => "10.0.48.9",
+ :inet => {
+ :address => "10.0.48.9"
+ },
:bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
:slaves => %w[ens18f0 ens18f1]
}
},
- :external_ipv4 => {
- :interface => "bond0.2",
+ :external => {
+ :interface => "bond0.3",
:role => :external,
- :family => :inet,
- :address => "130.117.76.9"
- },
- :external_ipv6 => {
- :interface => "bond0.2",
- :role => :external,
- :family => :inet6,
- :address => "2001:978:2:2C::172:9"
+ :inet => {
+ :address => "184.104.179.137"
+ },
+ :inet6 => {
+ :address => "2001:470:1:fa1::9"
+ }
}
}
},
:postgresql => {
- :versions => ["13"],
+ :versions => ["15"],
:settings => {
:defaults => {
- :work_mem => "300MB",
- :maintenance_work_mem => "10GB",
- :random_page_cost => "1.5",
- :effective_cache_size => "60GB",
- :fsync => "on",
+ :work_mem => "240MB",
:effective_io_concurrency => "500"
}
}
},
:nominatim => {
:state => "standalone",
- :enable_backup => false,
- :enable_git_updates => true,
- :dbadmins => %w[lonvia tomh],
- :dbcluster => "13/main",
+ :dbcluster => "15/main",
:postgis => "3",
:flatnode_file => "/ssd/nominatim/nodes.store",
:logdir => "/ssd/nominatim/log",
- :tablespaces => {
- "dosm" => "/ssd/tablespaces/dosm",
- "iosm" => "/ssd/tablespaces/iosm",
- "dplace" => "/ssd/tablespaces/dplace",
- "iplace" => "/ssd/tablespaces/iplace",
- "daddress" => "/ssd/tablespaces/daddress",
- "iaddress" => "/ssd/tablespaces/iaddress",
- "dsearch" => "/ssd/tablespaces/dsearch",
- "isearch" => "/ssd/tablespaces/isearch",
- "daux" => "/ssd/tablespaces/daux",
- "iaux" => "/ssd/tablespaces/iaux"
+ :api_flavour => "python",
+ :api_workers => 14,
+ :api_pool_size => 10,
+ :config => {
+ :forward_dependencies => "yes"
}
}
)
run_list(
- "role[equinix]",
+ "role[equinix-ams]",
"role[nominatim]"
)
default_attributes(
:networking => {
:interfaces => {
- :internal_ipv4 => {
+ :internal => {
:interface => "enp1s0f0.2801",
:role => :internal,
- :family => :inet,
- :address => "10.0.0.10"
+ :inet => {
+ :address => "10.0.0.10"
+ }
}
}
},
:shared_buffers => "64GB",
:work_mem => "64MB",
:maintenance_work_mem => "1GB",
- :effective_cache_size => "180GB",
- :effective_io_concurrency => "256",
- :random_page_cost => "1.1"
+ :effective_cache_size => "180GB"
}
}
},
-name "equinix"
-description "Role applied to all servers at Equinix"
+name "equinix-ams"
+description "Role applied to all servers at Equinix Amsterdam"
default_attributes(
:networking => {
:zone => "ams",
:inet => {
:prefix => "27",
- :gateway => "130.117.76.1"
+ :gateway => "184.104.179.129"
},
:inet6 => {
:prefix => "64",
- :gateway => "2001:978:2:2C::172:1",
- :routes => {
- "2001:978:2:2c::/64" => { :type => "unreachable" },
- "2001:4860::/32" => { :type => "unreachable" },
- "2a00:1450:4000::/37" => { :type => "unreachable" }
- }
+ :gateway => "2001:470:1:fa1::1"
}
}
}
},
+ :prometheus => {
+ :metrics => {
+ :host_location => {
+ :help => "Host location",
+ :labels => { :site => "amsterdam" }
+ }
+ }
+ },
:web => {
- :backends => %w[rails1 rails2 rails3],
:fileserver => "ironbelly",
:readonly_database_host => "snap-01.ams.openstreetmap.org",
:primary_cluster => true
override_attributes(
:networking => {
- :nameservers => ["66.28.0.45", "66.28.0.61"],
+ :nameservers => ["10.0.48.10", "8.8.8.8", "8.8.4.4"],
:search => ["ams.openstreetmap.org", "openstreetmap.org"]
},
:ntp => {
--- /dev/null
+name "equinix-dub"
+description "Role applied to all servers at Equinix Dublin"
+
+default_attributes(
+ :sysctl => {
+ :enable_bbr_10g => {
+ :comment => "Enable BBR. Equinix Dub has 10G uplink unlikely to buffer overrun",
+ :parameters => {
+ "net.ipv4.tcp_congestion_control" => "bbr",
+ "net.ipv4.tcp_notsent_lowat" => "16384"
+ }
+ }
+ },
+ :networking => {
+ :roles => {
+ :internal => {
+ :inet => {
+ :prefix => "20",
+ :gateway => "10.0.64.2",
+ :routes => {
+ "10.0.0.0/8" => { :via => "10.0.64.2" }
+ }
+ }
+ },
+ :external => {
+ :zone => "dub",
+ :inet => {
+ :prefix => "27",
+ :gateway => "184.104.226.97"
+ },
+ :inet6 => {
+ :prefix => "64",
+ :gateway => "2001:470:1:b3b::1"
+ }
+ }
+ }
+ },
+ :prometheus => {
+ :metrics => {
+ :host_location => {
+ :help => "Host location",
+ :labels => { :site => "dublin" }
+ }
+ }
+ },
+ :web => {
+ :fileserver => "fafnir",
+ :readonly_database_host => "snap-03.dub.openstreetmap.org"
+ }
+)
+
+override_attributes(
+ :networking => {
+ :nameservers => ["10.0.64.2", "8.8.8.8", "8.8.4.4"],
+ :search => ["dub.openstreetmap.org", "openstreetmap.org"]
+ },
+ :ntp => {
+ :servers => ["0.ie.pool.ntp.org", "1.ie.pool.ntp.org", "europe.pool.ntp.org"]
+ }
+)
+
+run_list(
+ "role[ie]"
+)
+++ /dev/null
-name "errol"
-description "Master role applied to errol"
-
-default_attributes(
- :devices => {
- :osdsk => {
- :comment => "First os disk",
- :type => "block",
- :bus => "scsi",
- :serial => "20004d927fffff800",
- :attrs => {
- "queue/scheduler" => "deadline",
- "queue/nr_requests" => "512"
- }
- },
- :homedsk => {
- :comment => "First home disk",
- :type => "block",
- :bus => "scsi",
- :serial => "20004d927fffff801",
- :attrs => {
- "queue/scheduler" => "deadline",
- "queue/nr_requests" => "512"
- }
- }
- },
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "eth0.2801",
- :role => :internal,
- :family => :inet,
- :address => "10.0.0.14"
- },
- :external_ipv4 => {
- :interface => "eth0.2800",
- :role => :external,
- :family => :inet,
- :address => "193.60.236.13"
- }
- }
- }
-)
-
-run_list(
- "role[ucl]",
- "role[tyan-s7010]",
- "role[dev]"
-)
+++ /dev/null
-name "eustace"
-description "Master role applied to eustace"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "eth0.2801",
- :role => :internal,
- :family => :inet,
- :address => "10.0.0.9"
- },
- :external_ipv4 => {
- :interface => "eth0.2800",
- :role => :external,
- :family => :inet,
- :address => "193.60.236.14"
- }
- }
- }
-)
-
-run_list(
- "role[ucl]",
- "role[hp-dl360-g6]",
- "role[piwik]"
-)
--- /dev/null
+name "faffy"
+description "Master role applied to faffy"
+
+default_attributes(
+ :networking => {
+ :interfaces => {
+ :internal => {
+ :interface => "bond0",
+ :role => :internal,
+ :inet => {
+ :address => "10.0.48.3"
+ },
+ :bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
+ :slaves => %w[eno1 eno2 eno3 eno4 eno5 eno6]
+ }
+ },
+ :external => {
+ :interface => "bond0.3",
+ :role => :external,
+ :inet => {
+ :address => "184.104.179.131"
+ },
+ :inet6 => {
+ :address => "2001:470:1:fa1::3"
+ }
+ }
+ }
+ }
+)
+
+run_list(
+ "role[equinix-ams]",
+ "role[dev]"
+)
--- /dev/null
+name "fafnir"
+description "Master role applied to fafnir"
+
+default_attributes(
+ :dhcpd => {
+ :first_address => "10.0.79.1",
+ :last_address => "10.0.79.254"
+ },
+ :exim => {
+ :routes => {
+ :openstreetmap => {
+ :comment => "openstreetmap.org",
+ :domains => ["openstreetmap.org"],
+ :host => ["shenron.openstreetmap.org"]
+ }
+ }
+ },
+ :networking => {
+ :interfaces => {
+ :internal => {
+ :interface => "bond0",
+ :role => :internal,
+ :inet => {
+ :address => "10.0.64.2"
+ },
+ :bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
+ :slaves => %w[eno1 eno2 eno3 eno4 eno49 eno50]
+ }
+ },
+ :external => {
+ :interface => "bond0.101",
+ :role => :external,
+ :inet => {
+ :address => "184.104.226.98"
+ },
+ :inet6 => {
+ :address => "2001:470:1:b3b::2"
+ }
+ }
+ }
+ },
+ :prometheus => {
+ :junos => {
+ "switch1" => { :address => "184.104.226.97", :labels => { "site" => "dublin" } }
+ },
+ :snmp => {
+ "pdu1" => { :address => "10.0.64.100", :modules => %w[apcups], :labels => { "site" => "dublin" } },
+ "pdu2" => { :address => "10.0.64.101", :modules => %w[apcups], :labels => { "site" => "dublin" } }
+ },
+ :metrics => {
+ :uplink_interface => {
+ :help => "Site uplink interface name",
+ :labels => { :site => "dublin", :name => "xe-[01]/2/[01]|ge-[01]/2/2" }
+ }
+ }
+ }
+)
+
+run_list(
+ "role[equinix-dub]",
+ "role[hp-g9]",
+ "role[gateway]",
+ "role[mail]",
+ "recipe[dhcpd]"
+)
+++ /dev/null
-name "faimaison"
-description "Role applied to all servers at FAImaison"
-
-default_attributes(
- :hosted_by => "FAImaison",
- :location => "France"
-)
-
-override_attributes(
- :ntp => {
- :servers => ["0.fr.pool.ntp.org", "1.fr.pool.ntp.org", "europe.pool.ntp.org"]
- }
-)
-
-run_list(
- "role[fr]"
-)
+++ /dev/null
-name "ffrl"
-description "Role applied to all servers at Freifunk Rheinland"
-
-default_attributes(
- :hosted_by => "Freifunk Rheinland",
- :location => "Berlin, Germany"
-)
-
-override_attributes(
- :ntp => {
- :servers => ["0.de.pool.ntp.org", "1.de.pool.ntp.org", "europe.pool.ntp.org"]
- }
-)
-
-run_list(
- "role[de]"
-)
+++ /dev/null
-name "firnen"
-description "Master role applied to firnen"
-
-default_attributes(
- :hardware => {
- :shm_size => "36g"
- },
- :networking => {
- :interfaces => {
- :external_ipv4 => {
- :interface => "enp6s0",
- :role => :external,
- :family => :inet,
- :address => "188.241.28.82",
- :prefix => "29",
- :gateway => "188.241.28.81"
- }
- }
- },
- :squid => {
- :version => 4,
- :cache_mem => "32768 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :tilecache => {
- :tile_parent => "germany.render.openstreetmap.org"
- }
-)
-
-run_list(
- "role[epix]",
- "role[tilecache]"
-)
+++ /dev/null
-name "forum"
-description "Role applied to all forum servers"
-
-default_attributes(
- :apache => {
- :mpm => "event",
- :timeout => 60,
- :event => {
- :server_limit => 18,
- :max_request_workers => 450,
- :min_spare_threads => 50,
- :max_spare_threads => 150,
- :listen_cores_buckets_ratio => 4
- }
- }
-)
-
-run_list(
- "recipe[forum]"
-)
description "Role applied to all OSMF servers"
default_attributes(
- :apt => {
- :sources => ["passenger"]
- },
:elasticsearch => {
- :version => "6.x",
+ :version => "7.x",
:cluster => {
:name => "foundation"
}
:innodb_buffer_pool_size => "512M",
:key_buffer_size => "64M",
:max_connections => "200",
- :query_cache_size => "48M",
- :query_cache_type => "1",
:sort_buffer_size => "8M",
:tmp_table_size => "48M"
}
"recipe[foundation::wiki]",
"recipe[foundation::board]",
"recipe[foundation::dwg]",
- "recipe[foundation::mwg]",
- "recipe[foundation::owg]"
+ "recipe[foundation::mwg]"
)
description "Master role applied to fume"
default_attributes(
- :hardware => {
- :shm_size => "6g"
- },
:networking => {
- :hostname => "seshat.civ.zcu.cz",
:interfaces => {
- :external_ipv4 => {
- :interface => "ens3",
+ :internal => {
+ :interface => "bond0",
+ :role => :internal,
+ :inet => {
+ :address => "10.0.64.16"
+ },
+ :bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
+ :slaves => %w[eno1 eno2 eno3 eno4 eno5 eno6]
+ }
+ },
+ :external => {
+ :interface => "bond0.101",
:role => :external,
- :family => :inet,
- :address => "147.228.60.16",
- :prefix => "24",
- :gateway => "147.228.60.1"
+ :inet => {
+ :address => "184.104.226.112"
+ },
+ :inet6 => {
+ :address => "2001:470:1:b3b::10"
+ }
}
}
- },
- :squid => {
- :version => 4,
- :cache_mem => "4096 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :tilecache => {
- :tile_parent => "czechia.render.openstreetmap.org"
}
)
run_list(
- "role[zcu]",
- "role[tilecache]"
+ "role[equinix-dub]",
+ "role[blog-staging]"
)
:comment => "Enable forwarding",
:parameters => { "net.ipv4.ip_forward" => "1" }
}
- },
- :exim => {
- :relay_from_hosts => ["10.0.0.0/8"]
}
)
run_list(
- "recipe[bind]"
+ "recipe[bind]",
+ "recipe[prometheus::smokeping]"
)
:list => false,
:transfer_logging => false,
:hosts_allow => [
- "193.60.236.20" # sarel
+ "184.104.226.102", # idris
+ "2001:470:1:b3b::6" # idris
]
}
}
:status => :user,
:shell => "/usr/bin/git-shell"
},
+ :stereo => {
+ :status => :user,
+ :shell => "/usr/bin/git-shell"
+ },
:git => {
:status => :role,
- :members => [:tomh, :grant, :matt, :lonvia, :yellowbkpk]
+ :members => [:tomh, :grant, :matt, :lonvia, :yellowbkpk, :stereo]
}
}
},
+++ /dev/null
-name "gorynych"
-description "Master role applied to gorynych"
-
-default_attributes(
- :hardware => {
- :ipmi => {
- :excluded_sensors => [3, 4]
- },
- :shm_size => "20g"
- },
- :munin => {
- :plugins => {
- :smart_sdc => {
- :smartctl_exit_status => { :warning => ":8" }
- },
- :smart_sdd => {
- :smartctl_exit_status => { :warning => ":8" }
- }
- }
- },
- :networking => {
- :interfaces => {
- :external_ipv4 => {
- :interface => "eth1",
- :role => :external,
- :family => :inet,
- :address => "5.45.248.21",
- :prefix => "30",
- :gateway => "5.45.248.22"
- },
- :external_ipv6 => {
- :interface => "eth1",
- :role => :external,
- :family => :inet6,
- :address => "2a02:6b8:b010:5065::a001",
- :prefix => "64",
- :gateway => "2a02:6b8:b010:5065::1"
- }
- }
- },
- :sysfs => {
- :md_tune => {
- :comment => "Tune the md sync performance so as not to kill system performance",
- :parameters => {
- "block/md0/md/sync_speed_min" => "1",
- "block/md0/md/sync_speed_max" => "100000"
- }
- }
- },
- :squid => {
- :version => 4,
- :cache_mem => "16384 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :nginx => {
- :cache => {
- :proxy => {
- :directory => "/store/nginx-cache/proxy-cache",
- :max_size => "32768M"
- }
- }
- },
- :tilecache => {
- :tile_parent => "moscow.render.openstreetmap.org"
- }
-)
-
-run_list(
- "role[yandex]",
- "role[tilecache]"
-)
--- /dev/null
+name "hp-dl360e-g8"
+description "Role applied to all HP DL360e G8 machines"
+++ /dev/null
-name "greenmini"
-description "Role applied to all servers at greenminihost"
-
-default_attributes(
- :accounts => {
- :users => {
- :joris => { :status => :administrator }
- }
- },
- :hosted_by => "greenminihost",
- :location => "Dronten, Netherlands"
-)
-
-override_attributes(
- :networking => {
- :nameservers => ["45.148.169.130", "185.200.102.102", "2a0a:aa42:222:2500::2500", "2a0a:aa42:321:2000::53"]
- },
- :ntp => {
- :servers => ["0.nl.pool.ntp.org", "1.nl.pool.ntp.org", "europe.pool.ntp.org"]
- }
-)
-
-run_list(
- "role[nl]"
-)
+++ /dev/null
-name "grindtooth"
-description "Master role applied to grindtooth"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "enp3s0f0.2801",
- :role => :internal,
- :family => :inet,
- :address => "10.0.0.19"
- },
- :external_ipv4 => {
- :interface => "enp3s0f0.2800",
- :role => :external,
- :family => :inet,
- :address => "193.60.236.15"
- }
- }
- }
-)
-
-run_list(
- "role[ucl]",
- "role[taginfo]"
-)
description "Master role applied to grisu"
default_attributes(
- :bind => {
- :clients => "bytemark"
- },
:networking => {
:interfaces => {
- :internal_ipv4 => {
+ :internal => {
:interface => "bond0",
:role => :internal,
- :family => :inet,
- :address => "10.0.32.20",
+ :inet => {
+ :address => "10.0.64.17"
+ },
:bond => {
- :slaves => %w[enp2s0f0 enp2s0f1]
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
+ :slaves => %w[eno1 eno2 eno3 eno4 eno5 eno6]
}
},
- :external_ipv4 => {
- :interface => "bond0.214",
+ :external => {
+ :interface => "bond0.101",
:role => :external,
- :family => :inet,
- :address => "89.16.162.20"
- },
- :external_ipv6 => {
- :interface => "bond0.214",
- :role => :external,
- :family => :inet6,
- :address => "2001:41c9:2:d6::20"
+ :inet => {
+ :address => "184.104.226.113"
+ },
+ :inet6 => {
+ :address => "2001:470:1:b3b::11"
+ }
}
}
- },
- :planet => {
- :replication => "disabled"
}
)
run_list(
- "role[bytemark]",
- "role[hp-dl180-g6]",
- "role[gateway]",
- "role[web-storage]",
- "role[backup]",
- "role[planet]"
- # "role[planetdump]"
+ "role[equinix-dub]",
+ "role[overpass-query]"
)
+++ /dev/null
-name "grnet"
-description "Role applied to all servers at GRNET"
-
-default_attributes(
- :accounts => {
- :users => {
- :grnet => { :status => :administrator }
- }
- },
- :hosted_by => "GRNET",
- :location => "Athens, Greece"
-)
-
-override_attributes(
- :ntp => {
- :servers => ["0.gr.pool.ntp.org", "1.gr.pool.ntp.org", "europe.pool.ntp.org"]
- }
-)
-
-run_list(
- "role[gr]"
-)
+++ /dev/null
-name "hetzner"
-description "Role applied to all servers at Hetzner"
-
-default_attributes(
- :hosted_by => "Hetzner"
-)
-
-override_attributes(
- :networking => {
- :nameservers => [
- "213.133.98.98",
- "213.133.99.99",
- "213.133.100.100",
- "2a01:4f8:0:a111::add:9898",
- "2a01:4f8:0:a102::add:9999",
- "2a01:4f8:0:a0a1::add:1010"
- ]
- },
- :ntp => {
- :servers => ["0.de.pool.ntp.org", "1.de.pool.ntp.org", "europe.pool.ntp.org"]
- }
-)
-
-run_list(
- "role[de]"
-)
--- /dev/null
+name "horntail"
+description "Master role applied to horntail"
+
+default_attributes(
+ :networking => {
+ :interfaces => {
+ :internal => {
+ :interface => "bond0",
+ :role => :internal,
+ :inet => {
+ :address => "10.0.64.10"
+ },
+ :bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
+ :slaves => %w[enp25s0f0 enp25s0f1]
+ }
+ },
+ :external => {
+ :interface => "bond0.101",
+ :role => :external,
+ :inet => {
+ :address => "184.104.226.106"
+ },
+ :inet6 => {
+ :address => "2001:470:1:b3b::a"
+ }
+ }
+ }
+ }
+)
+
+run_list(
+ "role[equinix-dub]",
+ "role[geodns]",
+ "role[planet]"
+)
description "Role applied to all HP DL180 G6 machines"
default_attributes(
- :munin => {
- :plugins => {
- :hpasmcli2_fans => {
- :fan1 => { :warning => "90", :critical => "100" },
- :fan2 => { :warning => "90", :critical => "100" },
- :fan3 => { :warning => "90", :critical => "100" },
- :fan4 => { :warning => "90", :critical => "100" }
- },
- :hpasmcli2_temp => {
- :temp3 => { :warning => "80.0", :critical => "85" }
- },
- :ipmi_temp => {
- :Temp1 => { :label => "Air Inlet" },
- :Temp2CPU1 => { :warning => ":", :label => "CPU 1" },
- :Temp3CPU2 => { :warning => ":", :label => "CPU 2" },
- :Temp4 => { :warning => ":", :label => "Memory 1" },
- :Temp5 => { :warning => ":", :label => "Memory 2" },
- :Temp8MemB0 => { :warning => ":", :label => "Memory 3" },
- :Temp9MemB0 => { :warning => ":", :label => "Memory 4" },
- :Temp10MemB0 => { :warning => ":", :label => "Memory 5" },
- :Temp12MemB1 => { :warning => ":", :label => "Memory 6" },
- :Temp13MemB1 => { :warning => ":", :label => "Memory 7" },
- :Temp14MemB1 => { :warning => ":", :label => "Memory 8" },
- :Temp15 => { :warning => ":", :label => "Main System Board 3" },
- :Temp16 => { :warning => ":", :label => "Main System Board 4" },
- :Temp17 => { :warning => ":", :label => "Main System Board 5" },
- :Temp18 => { :warning => ":", :label => "Main System Board 6" },
- :Temp19 => { :warning => ":", :label => "Main System Board 7" },
- :Temp20 => { :warning => ":", :label => "Main System Board 8" },
- :Temp21 => { :warning => ":", :label => "Main System Board 9" },
- :Temp26 => { :warning => ":", :label => "Drive Backplane 1" },
- :Temp27 => { :warning => ":", :label => "Drive Backplane 2" },
- :Temp28 => { :warning => ":", :label => "Drive Backplane 3" },
- :Temp29 => { :warning => ":", :label => "Drive Backplane 4" },
- :Temp30 => { :warning => ":", :label => "Drive Backplane 5" },
- :Temp31 => { :warning => ":", :label => "Drive Backplane 6" }
- }
- }
+ :hardware => {
+ :blacklisted_modules => %w[acpi_power_meter]
}
)
description "Role applied to all HP DL360 G6 machines"
default_attributes(
- :munin => {
- :plugins => {
- :hpasmcli2_fans => {
- :fan1 => { :warning => "85", :critical => "90" },
- :fan2 => { :warning => "85", :critical => "90" },
- :fan3 => { :warning => "85", :critical => "90" },
- :fan4 => { :warning => "85", :critical => "90" }
- },
- :ipmi_temp => {
- :Temp1 => { :label => "External Environment" },
- :Temp2 => { :warning => ":", :label => "CPU 1" },
- :Temp3 => { :warning => ":", :label => "CPU 2" },
- :Temp4 => { :warning => ":", :label => "Memory 1" },
- :Temp5 => { :warning => ":", :label => "Memory 2" },
- :Temp6 => { :warning => ":", :label => "Memory 3" },
- :Temp7 => { :warning => ":", :label => "Memory 4" },
- :Temp8 => { :warning => ":", :label => "Memory 5" },
- :Temp9 => { :warning => ":", :label => "Memory 6" },
- :Temp10 => { :warning => ":", :label => "Memory 7" },
- :Temp11 => { :warning => ":", :label => "Memory 8" },
- :Temp12 => { :warning => ":", :label => "PSU 1" },
- :Temp13 => { :warning => ":", :label => "PSU 2" },
- :Temp14 => { :warning => ":", :label => "Memory 9" },
- :Temp15 => { :warning => ":", :label => "CPU Zone 1" },
- :Temp16 => { :warning => ":", :label => "CPU Zone 2" },
- :Temp17 => { :warning => ":", :label => "Memory 10" },
- :Temp18 => { :warning => ":", :label => "CPU Zone 3" },
- :Temp19 => { :warning => ":", :label => "Peripheral Bay 1" },
- :Temp20 => { :warning => ":", :label => "Peripheral Bay 2" },
- :Temp21 => { :warning => ":", :label => "Peripheral Bay 3" },
- :Temp22 => { :warning => ":", :label => "Peripheral Bay 4" },
- :Temp23 => { :warning => ":", :label => "Peripheral Bay 5" },
- :Temp24 => { :warning => ":", :label => "Peripheral Bay 6" },
- :Temp25 => { :warning => ":", :label => "Peripheral Bay 7" },
- :Temp26 => { :warning => ":", :label => "Peripheral Bay 8" },
- :Temp27 => { :warning => ":", :label => "Drive Backplane" },
- :Temp28 => { :warning => ":", :label => "System Board" }
- }
- }
+ :hardware => {
+ :blacklisted_modules => %w[acpi_power_meter]
}
)
name "hp-g9"
description "Role applied to all HP G9 machines"
-
-default_attributes(
- :munin => {
- :plugins => {
- :hpasmcli2_temp => {
- :temp11 => { :warning => 85, :critical => 100 },
- :temp12 => { :warning => 85, :critical => 100 },
- :temp19 => { :warning => 85, :critical => 100 },
- :temp20 => { :warning => 85, :critical => 100 }
- }
- }
- }
-)
--- /dev/null
+name "idris"
+description "Master role applied to idris"
+
+default_attributes(
+ :networking => {
+ :interfaces => {
+ :internal => {
+ :interface => "bond0",
+ :role => :internal,
+ :inet => {
+ :address => "10.0.64.6"
+ },
+ :bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
+ :slaves => %w[eno1 eno2 eno3 eno4 eno49 eno50]
+ }
+ },
+ :external => {
+ :interface => "bond0.101",
+ :role => :external,
+ :inet => {
+ :address => "184.104.226.102"
+ },
+ :inet6 => {
+ :address => "2001:470:1:b3b::6"
+ }
+ }
+ }
+ }
+)
+
+run_list(
+ "role[equinix-dub]",
+ "role[hp-g9]",
+ "role[chef-server]",
+ "role[chef-repository]",
+ "role[dns]",
+ "role[git]",
+ "role[letsencrypt]",
+ "role[oxidized]",
+ "role[supybot]",
+ "recipe[serverinfo]"
+)
:parameters => {
"net.core.somaxconn" => 10000
}
- },
- :kernel_scheduler_tune => {
- :comment => "Tune kernel scheduler preempt",
- :parameters => {
- "kernel.sched_min_granularity_ns" => 10000000,
- "kernel.sched_wakeup_granularity_ns" => 15000000
- }
}
},
:nginx => {
description "Master role applied to ironbelly"
default_attributes(
- :apt => {
- :sources => ["ubuntugis-unstable"]
- },
- :bind => {
- :clients => "equinix"
- },
:dhcpd => {
:first_address => "10.0.63.1",
:last_address => "10.0.63.254"
},
:networking => {
:interfaces => {
- :internal_ipv4 => {
+ :internal => {
:interface => "bond0",
:role => :internal,
- :family => :inet,
- :address => "10.0.48.10",
+ :inet => {
+ :address => "10.0.48.10"
+ },
:bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
:slaves => %w[eth0 eth1]
}
},
- :external_ipv4 => {
- :interface => "bond0.2",
+ :external => {
+ :interface => "bond0.3",
:role => :external,
- :family => :inet,
- :address => "130.117.76.10"
- },
- :external_ipv6 => {
- :interface => "bond0.2",
- :role => :external,
- :family => :inet6,
- :address => "2001:978:2:2C::172:A"
+ :inet => {
+ :address => "184.104.179.138"
+ },
+ :inet6 => {
+ :address => "2001:470:1:fa1::a"
+ }
}
}
},
- :planet => {
- :replication => "enabled"
- },
:prometheus => {
+ :junos => {
+ "switch1" => { :address => "184.104.179.129", :labels => { "site" => "amsterdam" } }
+ },
:snmp => {
- "pdu1" => { :address => "10.0.48.100", :module => "apcups", :labels => { "site" => "amsterdam" } },
- "pdu2" => { :address => "10.0.48.101", :module => "apcups", :labels => { "site" => "amsterdam" } },
- "switch1" => { :address => "130.117.76.2", :module => "if_mib", :labels => { "site" => "amsterdam" } }
+ "pdu1" => { :address => "10.0.48.100", :modules => %w[apcups], :labels => { "site" => "amsterdam" } },
+ "pdu2" => { :address => "10.0.48.101", :modules => %w[apcups], :labels => { "site" => "amsterdam" } }
+ },
+ :metrics => {
+ :uplink_interface => {
+ :help => "Site uplink interface name",
+ :labels => { :site => "amsterdam", :name => "ge-[01]/2/[02]" }
+ }
+ }
+ },
+ :nginx => {
+ :cache => {
+ :proxy => {
+ :enable => true,
+ :keys_zone => "proxy_cache_zone:256M",
+ :inactive => "180d",
+ :max_size => "51200M"
+ }
}
},
:rsyncd => {
:modules => {
- :hosts => {
- :comment => "Host data",
- :path => "/home/hosts",
- :read_only => true,
- :write_only => false,
- :list => false,
- :uid => "tomh",
- :gid => "tomh",
- :transfer_logging => false,
- :hosts_allow => [
- "212.110.172.32", # shenron
- "2001:41c9:1:400::32", # shenron
- "212.159.112.221" # grant
- ]
- },
:logs => {
:comment => "Log files",
:path => "/store/logs",
:transfer_logging => false,
:hosts_allow => [
"193.60.236.0/24", # ucl external
- "10.0.48.0/20", # equinix internal
- "130.117.76.0/27", # equinix external
- "2001:978:2:2C::172:0/112", # equinix external
+ "10.0.48.0/20", # amsterdam internal
+ "184.104.179.128/27", # amsterdam external
+ "2001:470:1:fa1::/64", # amsterdam external
+ "10.0.64.0/20", # dublin internal
+ "184.104.226.96/27", # dublin external
+ "2001:470:1:b3b::/64", # dublin external
"10.0.32.0/20", # bytemark internal
"89.16.162.16/28", # bytemark external
"2001:41c9:2:d6::/64", # bytemark external
"127.0.0.0/8", # localhost
"::1" # localhost
- ],
- :nodes_allow => "roles:tilecache"
+ ]
}
}
}
)
run_list(
- "role[equinix]",
+ "role[equinix-ams]",
"role[gateway]",
- "role[web-storage]",
- "role[supybot]",
- "role[backup]",
- "role[planet]",
- "role[planetdump]",
"recipe[rsyncd]",
"recipe[dhcpd]",
- "recipe[tilelog]"
+ "recipe[imagery::za_ngi_aerial]"
)
+++ /dev/null
-name "iway"
-description "Role applied to all servers at iWay"
-
-default_attributes(
- :accounts => {
- :users => {
- :cramer => { :status => :administrator }
- }
- },
- :hosted_by => "iWay",
- :location => "Zurich, Switzerland",
- :networking => {
- :firewall => {
- :inet => [
- {
- :action => "ACCEPT",
- :source => "net:212.25.24.64/28",
- :dest => "fw",
- :proto => "udp",
- :dest_ports => "snmp",
- :source_ports => "1024:",
- :rate_limit => "-",
- :connection_limit => "-"
- }
- ]
- }
- }
-)
-
-override_attributes(
- :ntp => {
- :servers => ["0.ch.pool.ntp.org", "1.ch.pool.ntp.org", "europe.pool.ntp.org"]
- }
-)
-
-run_list(
- "role[ch]"
-)
--- /dev/null
+name "jakelong"
+description "Master role applied to jakelong"
+
+default_attributes(
+ :dhcpd => {
+ :first_address => "10.0.78.1",
+ :last_address => "10.0.78.254"
+ },
+ :networking => {
+ :interfaces => {
+ :internal => {
+ :interface => "bond0",
+ :role => :internal,
+ :inet => {
+ :address => "10.0.64.12"
+ },
+ :bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
+ :slaves => %w[eno1 eno2 eno3 eno4 ens1f0 ens1f1]
+ }
+ },
+ :external => {
+ :interface => "bond0.101",
+ :role => :external,
+ :inet => {
+ :address => "184.104.226.108"
+ },
+ :inet6 => {
+ :address => "2001:470:1:b3b::c"
+ }
+ }
+ }
+ }
+)
+
+run_list(
+ "role[equinix-dub]",
+ "role[hp-dl360e-g8]",
+ "role[community]",
+ "recipe[dhcpd]"
+)
+++ /dev/null
-name "jump"
-description "Role applied to all servers at Jump Networks"
-
-default_attributes(
- :hosted_by => "Jump Networks",
- :location => "London, England"
-)
-
-override_attributes(
- :networking => {
- :nameservers => ["185.73.44.3", "2001:ba8:0:2c02::", "2001:ba8:0:2c03::", "2001:ba8:0:2c04::"]
- },
- :ntp => {
- :servers => ["0.uk.pool.ntp.org", "1.uk.pool.ntp.org", "europe.pool.ntp.org"]
- }
-)
-
-run_list(
- "role[gb]"
-)
+++ /dev/null
-name "kalessin"
-description "Master role applied to kalessin"
-
-default_attributes(
- :hardware => {
- :shm_size => "20g"
- },
- :networking => {
- :interfaces => {
- :external_ipv4 => {
- :interface => "ens3",
- :role => :external,
- :family => :inet,
- :address => "185.66.195.245",
- :prefix => "28",
- :gateway => "185.66.195.241"
- },
- :external_ipv6 => {
- :interface => "ens3",
- :role => :external,
- :family => :inet6,
- :address => "2a03:2260:2000:1::5",
- :prefix => "64",
- :gateway => "2a03:2260:2000:1::1"
- }
- }
- },
- :squid => {
- :version => 4,
- :cache_mem => "16384 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :nginx => {
- :cache => {
- :proxy => {
- :keys_zone => "proxy_cache_zone:64M",
- :max_size => "2048M"
- }
- }
- },
- :tilecache => {
- :tile_parent => "germany.render.openstreetmap.org"
- }
-)
-
-run_list(
- "role[ffrl]",
- "role[tilecache]"
-)
default_attributes(
:networking => {
:interfaces => {
- :internal_ipv4 => {
+ :internal => {
:interface => "bond0",
:role => :internal,
- :family => :inet,
- :address => "10.0.48.50",
+ :inet => {
+ :address => "10.0.48.50"
+ },
:bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
:slaves => %w[enp1s0f0 enp1s0f1 enp2s0f0 enp2s0f1]
}
}
:shared_buffers => "64GB",
:work_mem => "64MB",
:maintenance_work_mem => "1GB",
- :effective_cache_size => "180GB",
- :effective_io_concurrency => "256",
- :random_page_cost => "1.1"
+ :effective_cache_size => "180GB"
+
}
}
},
)
run_list(
- "role[equinix]",
+ "role[equinix-ams]",
"role[db-slave]"
)
+++ /dev/null
-name "katla"
-description "Master role applied to katla"
-
-default_attributes(
- :devices => {
- :store_slow => {
- :comment => "RAID array mounted on /store/arrays/slow",
- :type => "block",
- :bus => "scsi",
- :serial => "3600605b005a0609019290f178be8de77",
- :attrs => {
- "queue/scheduler" => "deadline",
- "queue/nr_requests" => "975",
- "queue/rq_affinity" => "2"
- }
- },
- :store_fast => {
- :comment => "RAID array mounted on /store/arrays/fast",
- :type => "block",
- :bus => "scsi",
- :serial => "3600605b005a0726019d062ae23b426fd",
- :attrs => {
- "queue/scheduler" => "deadline",
- "queue/nr_requests" => "975",
- "queue/rq_affinity" => "2"
- }
- },
- :store_ssd_1 => {
- :comment => "First disk of RAID array mounted on /store/arrays/ssd",
- :type => "block",
- :bus => "ata",
- :serial => "INTEL_SSDSC2BA400G3_BTTV3141041E400HGN",
- :attrs => {
- "queue/scheduler" => "noop"
- }
- },
- :store_ssd_2 => {
- :comment => "Second disk of RAID array mounted on /store/arrays/ssd",
- :type => "block",
- :bus => "ata",
- :serial => "INTEL_SSDSC2BA400G3_BTTV3141044Q400HGN",
- :attrs => {
- "queue/scheduler" => "noop"
- }
- }
- },
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "bond0",
- :role => :internal,
- :family => :inet,
- :address => "10.0.32.40",
- :bond => {
- :slaves => %w[eth0 eth1]
- }
- }
- }
- },
- :postgresql => {
- :settings => {
- :defaults => {
- :shared_buffers => "64GB",
- :work_mem => "64MB",
- :maintenance_work_mem => "1GB",
- :effective_cache_size => "180GB"
- }
- }
- },
- :sysctl => {
- :postgres => {
- :comment => "Increase shared memory for postgres",
- :parameters => {
- "kernel.shmmax" => 66 * 1024 * 1024 * 1024,
- "kernel.shmall" => 66 * 1024 * 1024 * 1024 / 4096
- }
- }
- }
-)
-
-run_list(
- "role[bytemark]",
- "role[db-slave]"
-)
+++ /dev/null
-name "keizer"
-description "Master role applied to keizer"
-
-default_attributes(
- :hardware => {
- :shm_size => "12g"
- },
- :location => "Nuremberg, Germany",
- :networking => {
- :interfaces => {
- :external_ipv4 => {
- :interface => "eth0",
- :role => :external,
- :family => :inet,
- :address => "195.201.226.63",
- :prefix => "32",
- :gateway => "172.31.1.1"
- },
- :external_ipv6 => {
- :interface => "eth0",
- :role => :external,
- :family => :inet6,
- :address => "2a01:4f8:1c1c:bc54::1",
- :prefix => "64",
- :gateway => "fe80::1"
- }
- }
- },
- :squid => {
- :version => 4,
- :cache_mem => "8192 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 12800 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 16000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 22400 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 22800 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :tilecache => {
- :tile_parent => "germany.render.openstreetmap.org"
- }
-)
-
-run_list(
- "role[hetzner]",
- "role[tilecache]"
-)
}
}
},
- :munin => {
- :plugins => {
- :sensors_temp => {
- :temp6 => { :warning => "71.0", :critical => "76.0" },
- :temp7 => { :warning => "71.0", :critical => "76.0" },
- :temp8 => { :warning => "71.0", :critical => "76.0" },
- :temp9 => { :warning => "71.0", :critical => "76.0" }
- }
- }
- },
:networking => {
:interfaces => {
- :external_ipv4 => {
- :interface => "enp2s0f0",
- :role => :external,
- :family => :inet,
- :address => "178.250.74.36",
- :hwaddress => "d8:d3:85:5d:87:5e"
- },
- :external_ipv6 => {
+ :external => {
:interface => "enp2s0f0",
:role => :external,
- :family => :inet6,
- :address => "2a02:1658:4:0:dad3:85ff:fe5d:875e",
- :hwaddress => "d8:d3:85:5d:87:5e"
+ :inet => {
+ :address => "178.250.74.36"
+ },
+ :inet6 => {
+ :address => "2a02:1658:4:0:dad3:85ff:fe5d:875e"
+ }
}
}
}
+++ /dev/null
-name "kokosnuss"
-description "Master role applied to kokosnuss"
-
-default_attributes(
- :hardware => {
- :shm_size => "12g"
- },
- :networking => {
- :interfaces => {
- :external_ipv4 => {
- :interface => "venet0",
- :role => :external,
- :family => :inet,
- :address => "85.214.255.86",
- :prefix => "32",
- :gateway => "85.214.255.86"
- }
- },
- :wireguard => {
- :enabled => false
- }
- },
- :squid => {
- :version => 4,
- :cache_mem => "8192 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :tilecache => {
- :tile_parent => "germany.render.openstreetmap.org"
- }
-)
-
-run_list(
- "role[strato]",
- "role[tilecache]"
-)
--- /dev/null
+name "konqi"
+description "Master role applied to konqi"
+
+default_attributes(
+ :networking => {
+ :interfaces => {
+ :internal => {
+ :interface => "bond0",
+ :role => :internal,
+ :inet => {
+ :address => "10.0.64.7"
+ },
+ :bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
+ :slaves => %w[eno1 eno2 eno3 eno4 eno49 eno50]
+ }
+ },
+ :external => {
+ :interface => "bond0.101",
+ :role => :external,
+ :inet => {
+ :address => "184.104.226.103"
+ },
+ :inet6 => {
+ :address => "2001:470:1:b3b::7"
+ }
+ }
+ }
+ }
+)
+
+run_list(
+ "role[equinix-dub]",
+ "role[hp-g9]",
+ "role[wiki]"
+)
+++ /dev/null
-name "ladon"
-description "Master role applied to ladon"
-
-default_attributes(
- :hardware => {
- :shm_size => "36g"
- },
- :networking => {
- :interfaces => {
- :external_ipv4 => {
- :interface => "bond0",
- :role => :external,
- :family => :inet,
- :address => "83.212.2.116",
- :prefix => "29",
- :gateway => "83.212.2.113",
- :bond => {
- :mode => "802.3ad",
- :miimon => "100",
- :xmithashpolicy => "layer3+4",
- :slaves => %w[ens1f0 ens1f1]
- }
- },
- :external_ipv6 => {
- :interface => "bond0",
- :role => :external,
- :family => :inet6,
- :address => "2001:648:2ffe:4::116",
- :prefix => "64",
- :gateway => "2001:648:2ffe:4::1"
- }
- }
- },
- :squid => {
- :version => 4,
- :cache_mem => "32768 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 12800 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 16000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 22400 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 22800 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :tilecache => {
- :tile_parent => "athens.render.openstreetmap.org"
- }
-)
-
-run_list(
- "role[grnet]",
- "role[tilecache]"
-)
default_attributes(
:exim => {
:aliases => {
- "mailman-loop" => "/dev/null"
- }
+ "mailman-loop" => "/dev/null",
+ "prometheus" => "/dev/null"
+ },
+ :local_domains => [
+ "openstreetmap.org"
+ ]
}
)
+++ /dev/null
-name "lockheed"
-description "Master role applied to lockheed"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "bond0",
- :role => :internal,
- :family => :inet,
- :address => "10.0.48.16",
- :bond => {
- :slaves => %w[eth0 eth1]
- }
- },
- :external_ipv4 => {
- :interface => "bond0.2",
- :role => :external,
- :family => :inet,
- :address => "130.117.76.16"
- },
- :external_ipv6 => {
- :interface => "bond0.2",
- :role => :external,
- :family => :inet6,
- :address => "2001:978:2:2C::172:10"
- }
-
- }
- }
-)
-
-run_list(
- "role[equinix]"
-)
name "logstash-forwarder"
description "Role applied to all logstash forwarders"
-default_attributes(
- :apt => {
- :sources => ["elasticsearch6.x"]
- }
-)
-
run_list(
"recipe[logstash::forwarder]"
)
description "Master role applied to longma"
default_attributes(
- :exim => {
- :aliases => {
- :root => "ceasar"
- }
- },
- :hardware => {
- :shm_size => "20g"
- },
:networking => {
:interfaces => {
- :external_ipv4 => {
- :interface => "ens160",
- :role => :external,
- :family => :inet,
- :address => "140.110.240.7",
- :prefix => "24",
- :gateway => "140.110.240.254"
+ :internal => {
+ :interface => "bond0",
+ :role => :internal,
+ :inet => {
+ :address => "10.0.64.13"
+ },
+ :bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
+ :slaves => %w[enp68s0f0 enp68s0f1 enp68s0f2 enp68s0f3]
+ }
},
- :external_ipv6 => {
- :interface => "ens160",
+ :external => {
+ :interface => "bond0.101",
:role => :external,
- :family => :inet6,
- :address => "2001:e10:2000:240::7",
- :prefix => "64",
- :gateway => "2001:e10:2000:240::254"
+ :inet => {
+ :address => "184.104.226.109"
+ },
+ :inet6 => {
+ :address => "2001:470:1:b3b::d"
+ }
}
}
},
- :squid => {
- :version => 4,
- :cache_mem => "16384 MB",
- :cache_dir => [
- "rock /store.new-san/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store.new-san/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store.new-san/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store.new-san/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :nginx => {
- :cache => {
- :proxy => {
- :directory => "/store.new-san/nginx-cache/proxy-cache",
- :max_size => "65536M"
+ :postgresql => {
+ :versions => ["16"],
+ :settings => {
+ :defaults => {
+ :max_connections => "550",
+ :work_mem => "240MB",
+ :effective_io_concurrency => "500"
}
}
},
- :tilecache => {
- :tile_parent => "hsinchu.render.openstreetmap.org"
+ :nominatim => {
+ :state => "standalone",
+ :dbcluster => "16/main",
+ :postgis => "3",
+ :enable_qa_tiles => true,
+ :flatnode_file => "/ssd/nominatim/nodes.store",
+ :logdir => "/ssd/nominatim/log",
+ :api_flavour => "python",
+ :api_workers => 24,
+ :api_pool_size => 10,
+ :fpm_pools => {
+ "nominatim.openstreetmap.org" => {
+ :max_children => 200
+ }
+ },
+ :config => {
+ :forward_dependencies => "yes"
+ }
}
)
run_list(
- "role[nchc]",
- "role[tilecache]"
+ "role[equinix-dub]",
+ "role[nominatim]"
)
:hosted_by => "LyonIX",
:location => "Lyon, France",
:snmpd => {
- :clients => ["77.95.64.0/21"],
- :clients6 => ["2a03:9180::/32", "2001:7f8:47::/48"],
+ :clients => ["77.95.64.0/21", "2a03:9180::/32", "2001:7f8:47::/48"],
:community => "lyonix",
:location => "LYON",
:contact => "sysadm@rezopole.net"
+++ /dev/null
-name "lysator"
-description "Role applied to all servers at Lysator"
-
-default_attributes(
- :accounts => {
- :users => {
- :aoh => { :status => :administrator },
- :lysroot => { :status => :administrator }
- }
- },
- :hosted_by => "Lysator",
- :location => "Linköping, Sweden"
-)
-
-override_attributes(
- :networking => {
- :nameservers => ["130.236.254.225", "2001:6b0:17:f0a0::e1", "130.236.254.4"]
- },
- :ntp => {
- :servers => ["0.se.pool.ntp.org", "1.se.pool.ntp.org", "europe.pool.ntp.org"]
- }
-)
-
-run_list(
- "role[se]"
-)
"a.mx.openstreetmaps.org",
"a.mx.osm.io"
],
- :queue_run_max => 5,
+ :queue_run_max => 25,
+ :smtp_accept_max => 200,
:smarthost_name => "mail.openstreetmap.org",
- :smarthost_via => false,
- :dns_blacklists => ["zen.spamhaus.org"],
+ :smarthost_via => nil,
+ :dns_blacklists => ["zen.spamhaus.org!&0.255.255.0"],
:routes => {
:messages => {
:comment => "messages.openstreetmap.org",
:domains => ["messages.openstreetmap.org"],
- :host => ["spike-06.openstreetmap.org", "spike-07.openstreetmap.org", "spike-08.openstreetmap.org"]
+ :host => [
+ "spike-01.openstreetmap.org",
+ "spike-02.openstreetmap.org",
+ "spike-03.openstreetmap.org",
+ "spike-06.openstreetmap.org",
+ "spike-07.openstreetmap.org",
+ "spike-08.openstreetmap.org"
+ ]
},
:otrs => {
:comment => "otrs.openstreetmap.org",
:comment => "join.osmfoundation.org",
:domains => ["join.osmfoundation.org"],
:host => "ridley.ucl.openstreetmap.org"
+ },
+ :supporting => {
+ :comment => "supporting.openstreetmap.org",
+ :domains => ["supporting.openstreetmap.org"],
+ :host => "ridley.ucl.openstreetmap.org"
+ },
+ :community => {
+ :comment => "community.openstreetmap.org",
+ :domains => ["community.openstreetmap.org"],
+ :host => "jakelong.dub.openstreetmap.org::2500"
}
},
:dkim_selectors => {
"clamav" => "root",
"rails" => "root",
"trac" => "root",
- "munin" => "root",
"prometheus" => "root",
"www-data" => "root",
"osmbackup" => "root",
},
:private_aliases => "mail"
},
- :munin => {
- :plugins => {
- :exim_mailqueue => {
- :mails => {
- :warning => 500,
- :critical => 1000
- }
- }
+ :prometheus => {
+ :metrics => {
+ :exim_queue_limit => { :metric => 2500 }
}
}
)
--- /dev/null
+name "matomo"
+description "Role applied to all Matomo servers"
+
+default_attributes(
+ :apache => {
+ :mpm => "event",
+ :event => {
+ :server_limit => 30,
+ :max_request_workers => 1000,
+ :threads_per_child => 50,
+ :min_spare_threads => 75,
+ :max_spare_threads => 175,
+ :listen_cores_buckets_ratio => 4
+ }
+ },
+ :mysql => {
+ :settings => {
+ :mysqld => {
+ :innodb_buffer_pool_instances => "128",
+ :innodb_buffer_pool_size => "128GB",
+ :innodb_flush_log_at_trx_commit => "2",
+ :innodb_log_file_size => "16GB",
+ :join_buffer_size => "1GB",
+ :key_buffer_size => "0",
+ :max_connections => "64"
+ }
+ }
+ }
+)
+
+run_list(
+ "recipe[matomo]"
+)
description "Master role applied to meraxes"
default_attributes(
- :hardware => {
- :shm_size => "36g"
- },
:networking => {
:interfaces => {
- :external_ipv4 => {
+ :external => {
:interface => "enp1s0f0",
:role => :external,
- :family => :inet,
- :address => "51.15.185.90",
- :prefix => "24",
- :gateway => "51.15.185.1"
- },
- :external_ipv6 => {
- :interface => "enp1s0f0",
- :role => :external,
- :family => :inet6,
- :address => "2001:bc8:2d57:100:aa1e:84ff:fe72:e660",
- :prefix => "48",
- :gateway => "2001:bc8:2::2:258:1"
+ :inet => {
+ :address => "51.15.185.90",
+ :prefix => "24",
+ :gateway => "51.15.185.1"
+ },
+ :inet6 => {
+ :address => "2001:bc8:2d57:100:aa1e:84ff:fe72:e660",
+ :prefix => "48",
+ :gateway => "2001:bc8:2::2:258:1",
+ :dhcp => {
+ :duidtype => "link-layer",
+ :duidrawdata => "00:01:14:e9:19:1c:49:e0"
+ }
+ }
}
}
- },
- :squid => {
- :version => 4,
- :cache_mem => "32768 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 12800 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 16000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 22400 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 22800 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :tilecache => {
- :tile_parent => "france.render.openstreetmap.org"
}
)
run_list(
- "role[scaleway]",
- "role[tilecache]"
+ "role[scaleway]"
)
--- /dev/null
+name "muirdris"
+description "Master role applied to muirdris"
+
+default_attributes(
+ :memcached => {
+ :memory_limit => 128 * 1024
+ },
+ :networking => {
+ :interfaces => {
+ :internal => {
+ :interface => "bond0",
+ :role => :internal,
+ :inet => {
+ :address => "10.0.64.15"
+ },
+ :bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
+ :slaves => %w[eno1 eno2 eno3 eno4 eno5 eno6]
+ }
+ },
+ :external => {
+ :interface => "bond0.101",
+ :role => :external,
+ :inet => {
+ :address => "184.104.226.111"
+ },
+ :inet6 => {
+ :address => "2001:470:1:b3b::f"
+ }
+ }
+ }
+ }
+)
+
+run_list(
+ "role[equinix-dub]",
+ "role[gps-tile]"
+)
+++ /dev/null
-name "munin"
-description "Role applied to all munin servers"
-
-default_attributes(
- :munin => {
- :plugins => {
- :munin_update => {
- :contacts => "null"
- }
- }
- }
-)
-
-run_list(
- "recipe[munin::server]"
-)
--- /dev/null
+name "naga"
+description "Master role applied to naga"
+
+default_attributes(
+ :networking => {
+ :interfaces => {
+ :internal => {
+ :interface => "bond0",
+ :role => :internal,
+ :inet => {
+ :address => "10.0.64.8"
+ },
+ :bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
+ :slaves => %w[eno1 eno2 eno3 eno4 eno49 eno50]
+ }
+ },
+ :external => {
+ :interface => "bond0.101",
+ :role => :external,
+ :inet => {
+ :address => "184.104.226.104"
+ },
+ :inet6 => {
+ :address => "2001:470:1:b3b::8"
+ }
+ }
+ }
+ }
+)
+
+run_list(
+ "role[equinix-dub]",
+ "role[hp-g9]",
+ "role[subversion]",
+ "role[trac]",
+ "role[irc]",
+ "role[blogs]",
+ "role[switch2osm]",
+ "recipe[foundation::mastodon]",
+ "recipe[foundation::owg]",
+ "recipe[foundation::welcome]",
+ "recipe[stateofthemap::container]",
+ "recipe[hot]",
+ "recipe[ideditor]",
+ "recipe[dmca]"
+)
+++ /dev/null
-name "nchc"
-description "Role applied to all servers at NCHC"
-
-default_attributes(
- :accounts => {
- :users => {
- :steven => { :status => :administrator },
- :ceasar => { :status => :administrator }
- }
- },
- :hosted_by => "NCHC",
- :location => "Hsinchu, Taiwan",
- :networking => {
- :wireguard => { :keepalive => 180 }
- }
-)
-
-override_attributes(
- :networking => {
- :nameservers => ["140.110.16.1", "140.110.4.1"]
- },
- :ntp => {
- :servers => ["0.tw.pool.ntp.org", "1.tw.pool.ntp.org", "asia.pool.ntp.org"]
- }
-)
-
-run_list(
- "role[tw]"
-)
+++ /dev/null
-name "neak"
-description "Master role applied to neak"
-
-default_attributes(
- :hardware => {
- :shm_size => "14g"
- },
- :networking => {
- :interfaces => {
- :external_ipv4 => {
- :interface => "ens18",
- :role => :external,
- :family => :inet,
- :address => "89.234.177.142",
- :prefix => "26",
- :gateway => "89.234.177.129"
- }
- }
- },
- :squid => {
- :version => 4,
- :cache_mem => "10240 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 12800 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 16000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 22400 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 22800 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :tilecache => {
- :tile_parent => "france.render.openstreetmap.org"
- }
-)
-
-run_list(
- "role[faimaison]",
- "role[tilecache]"
-)
default_attributes(
:networking => {
:interfaces => {
- :external_ipv4 => {
+ :external => {
:interface => "bond0",
:mtu => 9000,
:role => :external,
- :family => :inet,
- :address => "45.85.134.91",
- :prefix => "31",
- :gateway => "45.85.134.90",
+ :inet => {
+ :address => "45.85.134.91",
+ :prefix => "31",
+ :gateway => "45.85.134.90"
+ },
+ :inet6 => {
+ :address => "2a05:46c0:100:1004:ffff:ffff:ffff:ffff",
+ :prefix => "64",
+ :gateway => "2a05:46c0:100:1004::"
+ },
:bond => {
:slaves => %w[eno1 eno2],
:mode => "802.3ad",
:lacprate => "fast"
}
- },
- :external_ipv6 => {
- :interface => "bond0",
- :role => :external,
- :family => :inet6,
- :address => "2a05:46c0:100:1004:ffff:ffff:ffff:ffff",
- :prefix => "64",
- :gateway => "2a05:46c0:100:1004::"
- }
- }
- },
- :postgresql => {
- :settings => {
- :defaults => {
- :shared_buffers => "8GB",
- :maintenance_work_mem => "7144MB",
- :effective_cache_size => "16GB"
}
}
},
- :sysctl => {
- :postgres => {
- :comment => "Increase shared memory for postgres",
+ :sysfs => {
+ :hdd_tune => {
+ :comment => "Tune the queue for improved performance",
:parameters => {
- "kernel.shmmax" => 9 * 1024 * 1024 * 1024,
- "kernel.shmall" => 9 * 1024 * 1024 * 1024 / 4096
- }
- }
- },
- :tile => {
- :database => {
- :cluster => "12/main",
- :postgis => "3"
- },
- :styles => {
- :default => {
- :tile_directories => [
- { :name => "/store/tiles/default", :min_zoom => 0, :max_zoom => 19 }
- ]
+ "block/sda/queue/nr_requests" => "975",
+ "block/sdb/queue/rotational" => "0"
}
}
}
)
run_list(
- "role[appliwave]",
- "role[tile]"
+ "role[appliwave]"
)
+++ /dev/null
-name "nepomuk"
-description "Master role applied to nepomuk"
-
-default_attributes(
- :hardware => {
- :shm_size => "14g"
- },
- :networking => {
- :firewall => {
- :inet => [
- {
- :action => "ACCEPT",
- :source => "net:77.95.64.120,77.95.64.131,77.95.64.139",
- :dest => "fw",
- :proto => "tcp",
- :dest_ports => "5666",
- :source_ports => "1024:",
- :rate_limit => "-",
- :connection_limit => "-"
- }
- ]
- },
- :interfaces => {
- :external_ipv4 => {
- :interface => "eth0",
- :role => :external,
- :family => :inet,
- :address => "77.95.65.39",
- :prefix => "27",
- :gateway => "77.95.65.33"
- },
- :external_ipv6 => {
- :interface => "eth0",
- :role => :external,
- :family => :inet6,
- :address => "2a03:9180:0:100::7",
- :prefix => "64",
- :gateway => "2a03:9180:0:100::1"
- }
- }
- },
- :sysctl => {
- :kvm => {
- :comment => "Tuning for KVM guest",
- :parameters => {
- "kernel.sched_min_granularity_ns" => 10000000,
- "kernel.sched_wakeup_granularity_ns" => 15000000
- }
- }
- },
- :squid => {
- :version => 4,
- :cache_mem => "10240 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :sysfs => {
- :hdd_tune => {
- :comment => "Tune the queue for improved performance",
- :parameters => {
- "block/vda/queue/nr_requests" => "128"
- }
- }
- },
- :tilecache => {
- :tile_parent => "france.render.openstreetmap.org"
- }
-)
-
-run_list(
- "role[lyonix]",
- "role[tilecache]"
-)
description "Master role applied to nidhogg"
default_attributes(
- :hardware => {
- :shm_size => "14g"
- },
:networking => {
:interfaces => {
- :external_ipv4 => {
- :interface => "ens18",
- :role => :external,
- :family => :inet,
- :address => "130.236.254.221",
- :prefix => "24",
- :gateway => "130.236.254.1"
- },
- :external_ipv6 => {
- :interface => "ens18",
+ :external => {
+ :interface => "bond0",
:role => :external,
- :family => :inet6,
- :address => "2001:6b0:17:f0a0::dd",
- :prefix => "64",
- :gateway => "2001:6b0:17:f0a0::1"
+ :inet => {
+ :address => "194.71.11.111",
+ :prefix => "25",
+ :gateway => "194.71.11.1"
+ },
+ :inet6 => {
+ :address => "2001:6b0:19:2::111",
+ :prefix => "64",
+ :gateway => "2001:6b0:19:2::1"
+ },
+ :bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
+ :slaves => %w[enp68s0f0 enp68s0f1 enp68s0f2 enp68s0f3]
+ }
}
}
},
- :squid => {
- :version => 4,
- :cache_mem => "10240 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
+ :postgresql => {
+ :settings => {
+ :defaults => {
+ :effective_cache_size => "16GB"
+ }
+ }
},
- :tilecache => {
- :tile_parent => "sweden.render.openstreetmap.org"
+ :sysctl => {
+ :postgres => {
+ :comment => "Increase shared memory for postgres",
+ :parameters => {
+ "kernel.shmmax" => 9 * 1024 * 1024 * 1024,
+ "kernel.shmall" => 9 * 1024 * 1024 * 1024 / 4096
+ }
+ }
+ },
+ :tile => {
+ :database => {
+ :cluster => "16/main",
+ :postgis => "3"
+ },
+ :mapnik => "3.1",
+ :styles => {
+ :default => {
+ :tile_directories => [
+ { :name => "/store/tiles/default", :min_zoom => 0, :max_zoom => 19 }
+ ]
+ }
+ }
}
)
run_list(
- "role[lysator]",
- "role[tilecache]"
+ "role[umu]",
+ "role[tile]"
)
:accounts => {
:users => {
:lonvia => { :status => :administrator },
- :twain => { :status => :administrator },
:nominatim => {
:status => :role,
- :members => [:lonvia, :tomh, :twain]
+ :members => [:lonvia, :tomh]
}
}
},
- :apache => {
- :mpm => "event",
- :timeout => 30,
- :keepalive => false,
- :reqtimeout => true,
- :event => {
- :server_limit => 100,
- :max_request_workers => 2400,
- :threads_per_child => 50,
- :min_spare_threads => 125,
- :max_spare_threads => 925,
- :async_request_worker_factor => 4,
- :listen_cores_buckets_ratio => 6
- }
- },
:networking => {
:firewall => {
:http_rate_limit => "s:2/sec:15"
:defaults => {
:max_connections => "450",
:synchronous_commit => "off",
- :checkpoint_segments => "32",
:checkpoint_timeout => "10min",
:checkpoint_completion_target => "0.9",
:jit => "off",
:shared_buffers => "2GB",
- :autovacuum_max_workers => "1"
+ :autovacuum_max_workers => "1",
+ :max_parallel_workers_per_gather => "0",
+ :maintenance_work_mem => "10GB",
+ :seq_page_cost => "3.0",
+ :random_page_cost => "3.0",
+ :effective_cache_size => "60GB",
+ :wal_level => "minimal",
+ :max_wal_senders => "0"
}
}
},
"kernel.shmall" => 26 * 1024 * 1024 * 1024 / 4096
}
},
- :kernel_scheduler_tune => {
- :comment => "Tune kernel scheduler preempt",
- :parameters => {
- "kernel.sched_min_granularity_ns" => 10000000,
- "kernel.sched_wakeup_granularity_ns" => 15000000
- }
- },
:swappiness => {
:comment => "Reduce swap usage",
:parameters => {
"net.netfilter.nf_conntrack_max" => "196608"
}
}
+ },
+ :nominatim => {
+ :dbadmins => %w[lonvia tomh],
+ :tablespaces => {
+ "dosm" => "/ssd/tablespaces/dosm",
+ "iosm" => "/ssd/tablespaces/iosm",
+ "dplace" => "/ssd/tablespaces/dplace",
+ "iplace" => "/ssd/tablespaces/iplace",
+ "daddress" => "/ssd/tablespaces/daddress",
+ "iaddress" => "/ssd/tablespaces/iaddress",
+ "dsearch" => "/ssd/tablespaces/dsearch",
+ "isearch" => "/ssd/tablespaces/isearch",
+ "daux" => "/ssd/tablespaces/daux",
+ "iaux" => "/ssd/tablespaces/iaux"
+ }
}
)
+++ /dev/null
-name "noquiklos"
-description "Master role applied to noquiklos"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "eth0.2801",
- :role => :internal,
- :family => :inet,
- :address => "10.0.0.13"
- },
- :external_ipv4 => {
- :interface => "eth0.2800",
- :role => :external,
- :family => :inet,
- :address => "193.60.236.16"
- }
- }
- }
-)
-
-run_list(
- "role[ucl]",
- "role[hp-dl360-g6]",
- "role[gps-tile]"
-)
--- /dev/null
+name "norbert"
+description "Master role applied to norbert"
+
+default_attributes(
+ :networking => {
+ :interfaces => {
+ :internal => {
+ :interface => "bond0",
+ :role => :internal,
+ :inet => {
+ :address => "10.0.48.17"
+ },
+ :bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
+ :slaves => %w[enp25s0f0 enp25s0f1]
+ }
+ },
+ :external => {
+ :interface => "bond0.3",
+ :role => :external,
+ :inet => {
+ :address => "184.104.179.145"
+ },
+ :inet6 => {
+ :address => "2001:470:1:fa1::11"
+ }
+ }
+ }
+ },
+ :planet => {
+ :replication => "enabled"
+ }
+)
+
+run_list(
+ "role[equinix-ams]",
+ "role[geodns]",
+ "role[backup]",
+ "role[planet]",
+ "role[planetdump]",
+ "recipe[tilelog]"
+)
default_attributes(
:networking => {
:interfaces => {
- :internal_ipv4 => {
+ :internal => {
:interface => "bond0",
:role => :internal,
- :family => :inet,
- :address => "10.0.48.15",
+ :inet => {
+ :address => "10.0.48.15"
+ },
:bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
:slaves => %w[eno1 eno2]
}
},
- :external_ipv4 => {
- :interface => "bond0.2",
+ :external => {
+ :interface => "bond0.3",
:role => :external,
- :family => :inet,
- :address => "130.117.76.15"
- },
- :external_ipv6 => {
- :interface => "bond0.2",
- :role => :external,
- :family => :inet6,
- :address => "2001:978:2:2C::172:F"
+ :inet => {
+ :address => "184.104.179.143"
+ },
+ :inet6 => {
+ :address => "2001:470:1:fa1::f"
+ }
}
}
},
:postgresql => {
:settings => {
:defaults => {
- :shared_buffers => "8GB",
- :maintenance_work_mem => "7144MB",
:effective_cache_size => "16GB"
}
}
},
:tile => {
:database => {
- :cluster => "12/main",
+ :cluster => "16/main",
:postgis => "3"
},
+ :mapnik => "3.1",
:styles => {
:default => {
:tile_directories => [
)
run_list(
- "role[equinix]",
+ "role[equinix-ams]",
"role[tile]"
)
+++ /dev/null
-name "orm"
-description "Master role applied to orm"
-
-default_attributes(
- :devices => {
- :arecavoltune => {
- :comment => "Tune scheduler for Areca",
- :type => "block",
- :bus => "scsi",
- :serial => "2001b4d20*",
- :attrs => {
- "queue/scheduler" => "deadline",
- "queue/nr_requests" => "512",
- "queue/read_ahead_kb" => "2048"
- }
- }
- },
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "bond0",
- :role => :internal,
- :family => :inet,
- :address => "10.0.48.3",
- :bond => {
- :slaves => %w[eth0 eth1]
- }
- },
- :external_ipv4 => {
- :interface => "bond0.2",
- :role => :external,
- :family => :inet,
- :address => "130.117.76.3"
- },
- :external_ipv6 => {
- :interface => "bond0.2",
- :role => :external,
- :family => :inet6,
- :address => "2001:978:2:2C::172:3"
- }
- }
- },
- :sysctl => {
- :postgres => {
- :comment => "Increase shared memory for postgres",
- :parameters => {
- "kernel.shmmax" => 9 * 1024 * 1024 * 1024,
- "kernel.shmall" => 9 * 1024 * 1024 * 1024 / 4096
- }
- }
- }
-)
-
-run_list(
- "role[equinix]",
- "role[tyan-s7010]"
-)
},
:hosted_by => "OSUOSL",
:location => "Corvallis, Oregon",
- :timezone => "PST8PDT",
+ :timezone => "US/Pacific",
:networking => {
:roles => {
:external => {
:group => "www-data",
:home_directory => "/opt/otrs"
},
+ :otrs_communications => {
+ :comment => "communications@otrs.openstreetmap.org",
+ :domains => ["otrs.openstreetmap.org"],
+ :local_parts => ["communications"],
+ :command => "/opt/otrs/bin/otrs.Console.pl Maint::PostMaster::Read --target-queue 'Communications Working Group'",
+ :user => "otrs",
+ :group => "www-data",
+ :home_directory => "/opt/otrs"
+ },
+ :otrs_communications_freebies => {
+ :comment => "freebies@otrs.openstreetmap.org",
+ :domains => ["otrs.openstreetmap.org"],
+ :local_parts => ["freebies"],
+ :command => "/opt/otrs/bin/otrs.Console.pl Maint::PostMaster::Read --target-queue 'Communications Working Group::Freebies'",
+ :user => "otrs",
+ :group => "www-data",
+ :home_directory => "/opt/otrs"
+ },
:otrs_support => {
:comment => "support@otrs.openstreetmap.org",
:domains => ["otrs.openstreetmap.org"],
--- /dev/null
+name "overpass-query"
+description "Role applied to overpass servers for the query feature."
+
+default_attributes(
+ :accounts => {
+ :users => {
+ :lonvia => { :status => :administrator },
+ :overpass => {
+ :status => :role,
+ :members => [:lonvia, :tomh]
+ }
+ }
+ },
+ :overpass => {
+ :fqdn => "query.openstreetmap.org",
+ :meta_mode => "no",
+ :compression_mode => "lz4",
+ :restricted_api => true
+ },
+ :prometheus => {
+ :files => %w[
+ /srv/query.openstreetmap.org/diffs/latest.osc
+ ]
+ }
+)
+
+run_list(
+ "recipe[overpass::default]"
+)
--- /dev/null
+name "oxidized"
+description "Role applied to all oxidized servers"
+
+default_attributes(
+ :accounts => {
+ :users => {
+ :oxidized => {
+ :status => :role,
+ :members => [:grant, :tomh]
+ }
+ }
+ }
+)
+
+run_list(
+ "recipe[oxidized]"
+)
--- /dev/null
+name "palulukon"
+description "Master role applied to palulukon"
+
+default_attributes(
+ :networking => {
+ :firewall => {
+ :allowlist => ["172.31.0.2"]
+ },
+ :interfaces => {
+ :external => {
+ :interface => "ens5",
+ :role => :external,
+ :inet => {
+ :address => "172.31.37.101",
+ :prefix => "20",
+ :gateway => "172.31.32.1",
+ :public_address => "3.144.0.72"
+ }
+ }
+ }
+ },
+ :postgresql => {
+ :settings => {
+ :defaults => {
+ :effective_cache_size => "16GB"
+ }
+ }
+ },
+ :sysctl => {
+ :postgres => {
+ :comment => "Increase shared memory for postgres",
+ :parameters => {
+ "kernel.shmmax" => 9 * 1024 * 1024 * 1024,
+ "kernel.shmall" => 9 * 1024 * 1024 * 1024 / 4096
+ }
+ }
+ },
+ :tile => {
+ :database => {
+ :cluster => "16/main",
+ :postgis => "3"
+ },
+ :mapnik => "3.1",
+ :styles => {
+ :default => {
+ :tile_directories => [
+ { :name => "/store/tiles/default", :min_zoom => 0, :max_zoom => 19 }
+ ]
+ }
+ }
+ }
+)
+
+override_attributes(
+ :networking => {
+ :nameservers => ["172.31.0.2"]
+ }
+)
+
+run_list(
+ "role[aws-us-east-2]",
+ "role[tile]"
+)
}
},
:hosted_by => "Université de Pau et des Pays de l'Adour",
- :location => "Pau, France",
- :munin => {
- :allow => ["10.64.1.11"]
- }
+ :location => "Pau, France"
)
override_attributes(
--- /dev/null
+name "piasa"
+description "Master role applied to piasa"
+
+default_attributes(
+ :networking => {
+ :interfaces => {
+ :external => {
+ :interface => "bond0",
+ :role => :external,
+ :inet => {
+ :address => "140.211.167.101"
+ },
+ :inet6 => {
+ :address => "2605:bc80:3010:700::8cd3:a765"
+ },
+ :bond => {
+ :slaves => %w[eno1 eno2 eno3 eno4 eno5 eno6]
+ }
+ }
+ }
+ },
+ :postgresql => {
+ :settings => {
+ :defaults => {
+ :effective_cache_size => "16GB"
+ }
+ }
+ },
+ :sysctl => {
+ :postgres => {
+ :comment => "Increase shared memory for postgres",
+ :parameters => {
+ "kernel.shmmax" => 9 * 1024 * 1024 * 1024,
+ "kernel.shmall" => 9 * 1024 * 1024 * 1024 / 4096
+ }
+ }
+ },
+ :tile => {
+ :database => {
+ :cluster => "16/main",
+ :postgis => "3"
+ },
+ :mapnik => "3.1",
+ :styles => {
+ :default => {
+ :tile_directories => [
+ { :name => "/store/tiles/default", :min_zoom => 0, :max_zoom => 19 }
+ ]
+ }
+ },
+ }
+)
+
+run_list(
+ "role[osuosl]",
+ "role[tile]"
+)
+++ /dev/null
-name "piwik"
-description "Role applied to all Piwik servers"
-
-default_attributes(
- :apache => {
- :mpm => "event",
- :event => {
- :server_limit => 18,
- :max_request_workers => 450,
- :min_spare_threads => 50,
- :max_spare_threads => 150,
- :listen_cores_buckets_ratio => 4
- }
- },
- :mysql => {
- :settings => {
- :mysqld => {
- :innodb_buffer_pool_instances => "8",
- :innodb_buffer_pool_size => "16GB",
- :innodb_flush_log_at_trx_commit => "2"
- }
- }
- }
-)
-
-run_list(
- "recipe[piwik]"
-)
+++ /dev/null
-name "planet-current"
-description "Role applied to all servers needing an up to date planet file"
-
-default_attributes(
- :accounts => {
- :users => {
- :planet => {
- :status => :role
- }
- }
- }
-)
-
-run_list(
- "recipe[planet::current]"
-)
description "Role applied to all planet servers"
default_attributes(
+ :apache => {
+ :mpm => "event",
+ :keepalive => true,
+ :event => {
+ :server_limit => 30,
+ :max_request_workers => 1000,
+ :threads_per_child => 50,
+ :min_spare_threads => 75,
+ :max_spare_threads => 525,
+ :listen_cores_buckets_ratio => 4
+ }
+ },
+ :networking => {
+ :firewall => {
+ :http_connection_limit => 10
+ }
+ },
+ :prometheus => {
+ :files => %w[
+ /store/planet/notes/planet-notes-latest.osn.bz2
+ /store/planet/pbf/planet-latest.osm.pbf
+ /store/planet/planet/changesets-latest.osm.bz2
+ /store/planet/planet/discussions-latest.osm.bz2
+ /store/planet/planet/planet-latest.osm.bz2
+ /store/planet/replication/changesets/state.yaml
+ /store/planet/replication/day/state.txt
+ /store/planet/replication/hour/state.txt
+ /store/planet/replication/minute/state.txt
+ ]
+ },
:rsyncd => {
:modules => {
:planet => {
:ignore_nonreadable => true,
:timeout => 3600,
:refuse_options => ["checksum"]
+ },
+ :statistics => {
+ :comment => "Statistics",
+ :path => "/store/planet/statistics",
+ :read_only => false,
+ :write_only => true,
+ :list => false,
+ :uid => "planet",
+ :gid => "planet",
+ :transfer_logging => false,
+ :nodes_allow => "roles:web-statistics"
}
}
- },
- :networking => {
- :firewall => {
- :http_connection_limit => 10
- }
- },
- :apache => {
- :mpm => "event",
- :keepalive => true,
- :event => {
- :server_limit => 20,
- :max_request_workers => 1000,
- :threads_per_child => 50,
- :min_spare_threads => 75,
- :max_spare_threads => 525,
- :listen_cores_buckets_ratio => 4
- }
}
)
"role[web-db]",
"recipe[planet]",
"recipe[planet::replication]",
- "recipe[nfs::server]",
"recipe[rsyncd]"
)
description "Role applied to all prometheus servers"
default_attributes(
- :postgresql => {
- :settings => {
- :defaults => {
- :max_connections => "500",
- :shared_buffers => "48GB",
- :work_mem => "8MB",
- :maintenance_work_mem => "2GB",
- :effective_io_concurrency => "200",
- :max_worker_processes => "67",
- :max_parallel_workers_per_gather => "28",
- :max_parallel_workers => "56",
- :wal_buffers => "16MB",
- :max_wal_size => "32GB",
- :min_wal_size => "4GB",
- :checkpoint_completion_target => "0.9",
- :random_page_cost => "1.1",
- :effective_cache_size => "144GB",
- :default_statistics_target => "500",
- :log_autovacuum_min_duration => "0",
- :autovacuum_max_workers => "10",
- :autovacuum_naptime => "10",
- :autovacuum_multixact_freeze_max_age => "200000000",
- :max_locks_per_transaction => "512"
- }
+ :apache => {
+ :evasive => {
+ :enable => false
}
}
)
run_list(
- "recipe[prometheus::server]"
+ "recipe[awscli]",
+ "recipe[prometheus::server]",
+ "recipe[prometheus::smokeping]"
)
+++ /dev/null
-name "pummelzacken"
-description "Master role applied to pummelzacken"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :bond => {
- :interface => "bond0",
- :bond => {
- :slaves => %w[eno1 enp5s0f0]
- }
- },
- :internal_ipv4 => {
- :interface => "bond0.2801",
- :role => :internal,
- :family => :inet,
- :address => "10.0.0.20"
- },
- :external_ipv4 => {
- :interface => "bond0.2800",
- :role => :external,
- :family => :inet,
- :address => "193.60.236.18"
- }
- }
- },
- :postgresql => {
- :versions => ["13"],
- :settings => {
- :defaults => {
- :listen_addresses => "10.0.0.20",
- :work_mem => "160MB",
- :maintenance_work_mem => "10GB",
- :random_page_cost => "1.5",
- :effective_cache_size => "60GB",
- :effective_io_concurrency => "256",
- :fsync => "on"
- }
- }
- },
- :apache => {
- :event => {
- :max_request_workers => 3000,
- :threads_per_child => 70
- }
- },
- :nominatim => {
- :state => "standalone",
- :dbadmins => %w[lonvia tomh],
- :dbcluster => "13/main",
- :postgis => "3",
- :enable_backup => true,
- :flatnode_file => "/ssd/nominatim/nodes.store",
- :tablespaces => {
- "dosm" => "/ssd/tablespaces/dosm",
- "iosm" => "/ssd/tablespaces/iosm",
- "dplace" => "/ssd/tablespaces/dplace",
- "iplace" => "/ssd/tablespaces/iplace",
- "daddress" => "/ssd/tablespaces/daddress",
- "iaddress" => "/ssd/tablespaces/iaddress",
- "dsearch" => "/ssd/tablespaces/dsearch",
- "isearch" => "/ssd/tablespaces/isearch",
- "daux" => "/data/tablespaces/daux",
- "iaux" => "/data/tablespaces/iaux"
- }
- }
-)
-
-run_list(
- "role[ucl]",
- "role[nominatim]"
-)
+++ /dev/null
-name "pyrene"
-description "Master role applied to pyrene"
-
-default_attributes(
- :munin => {
- :plugins => {
- :hpasmcli2_temp => {
- :temp15 => { :warning => "59.5", :critical => "70" },
- :temp17 => { :warning => "59.5", :critical => "70" }
- },
- :hpasmcli2_fans => {
- :fan1 => { :warning => "95", :critical => "100" },
- :fan2 => { :warning => "95", :critical => "100" },
- :fan3 => { :warning => "95", :critical => "100" },
- :fan4 => { :warning => "95", :critical => "100" },
- :fan5 => { :warning => "95", :critical => "100" },
- :fan6 => { :warning => "95", :critical => "100" },
- :fan7 => { :warning => "95", :critical => "100" },
- :fan8 => { :warning => "95", :critical => "100" }
- }
- }
- },
- :networking => {
- :interfaces => {
- :external_ipv4 => {
- :interface => "eno1",
- :role => :external,
- :family => :inet,
- :address => "140.211.167.98"
- },
- :external_ipv6 => {
- :interface => "eno1",
- :role => :external,
- :family => :inet6,
- :address => "2605:bc80:3010:700::8cd3:a762"
- }
- }
- },
- :postgresql => {
- :settings => {
- :defaults => {
- :shared_buffers => "8GB",
- :maintenance_work_mem => "7144MB",
- :effective_cache_size => "16GB"
- }
- }
- },
- :sysctl => {
- :postgres => {
- :comment => "Increase shared memory for postgres",
- :parameters => {
- "kernel.shmmax" => 9 * 1024 * 1024 * 1024,
- "kernel.shmall" => 9 * 1024 * 1024 * 1024 / 4096
- }
- }
- },
- :tile => {
- :database => {
- :cluster => "12/main",
- :postgis => "3"
- },
- :styles => {
- :default => {
- :tile_directories => [
- { :name => "/store/tiles/default", :min_zoom => 0, :max_zoom => 19 }
- ]
- }
- }
- }
-)
-
-run_list(
- "role[osuosl]",
- "role[tile]"
-)
+++ /dev/null
-name "ramoth"
-description "Master role applied to ramoth"
-
-default_attributes(
- :devices => {
- :store_openstreetmap => {
- :comment => "RAID array mounted on /store/postgresql/openstreetmap",
- :type => "block",
- :bus => "scsi",
- :serial => "3600605b00599aa401c02b4f53bf5c805",
- :attrs => {
- "queue/scheduler" => "deadline",
- "queue/nr_requests" => "975"
- }
- },
- :store_system => {
- :comment => "RAID array mounted on /store/postgresql/system",
- :type => "block",
- :bus => "scsi",
- :serial => "3600605b0039483a017092ff8fa5a6332",
- :attrs => {
- "queue/scheduler" => "deadline",
- "queue/nr_requests" => "975"
- }
- }
- },
- :hardware => {
- :watchdog => "w83627hf_wdt"
- },
- :munin => {
- :plugins => {
- :smart_sg0_33 => {
- :smartctl_exit_status => { :warning => ":8" }
- },
- :smart_sg0_34 => {
- :smartctl_exit_status => { :warning => ":8" }
- }
- }
- },
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "bond0",
- :role => :internal,
- :family => :inet,
- :address => "10.0.48.5",
- :bond => {
- :slaves => %w[enp7s0f0 enp7s0f1]
- }
- }
- }
- }
-)
-
-run_list(
- "role[equinix]"
-)
}
},
:location => "Zagreb, Croatia",
- :munin => {
- :plugins => {
- :sensors_temp => {
- :temp1 => { :warning => "85.0" },
- :temp2 => { :warning => "85.0" },
- :temp3 => { :warning => "85.0" },
- :temp4 => { :warning => "85.0" },
- :temp5 => { :warning => "85.0" },
- :temp6 => { :warning => "85.0" },
- :temp8 => { :warning => "85.0" },
- :temp9 => { :warning => "85.0" },
- :temp10 => { :warning => "85.0" },
- :temp11 => { :warning => "85.0" },
- :temp12 => { :warning => "85.0" },
- :temp13 => { :warning => "85.0" }
- }
- }
- },
:networking => {
:interfaces => {
- :external_ipv4 => {
+ :external => {
:interface => "eno1",
:role => :external,
- :family => :inet,
- :address => "10.5.0.77",
- :prefix => "16",
- :gateway => "10.5.0.1",
- :public_address => "161.53.248.77"
- }
- }
- },
- :postgresql => {
- :settings => {
- :defaults => {
- :shared_buffers => "8GB",
- :maintenance_work_mem => "7144MB",
- :effective_cache_size => "16GB"
- }
- }
- },
- :sysctl => {
- :postgres => {
- :comment => "Increase shared memory for postgres",
- :parameters => {
- "kernel.shmmax" => 9 * 1024 * 1024 * 1024,
- "kernel.shmall" => 9 * 1024 * 1024 * 1024 / 4096
- }
- }
- },
- :tile => {
- :database => {
- :cluster => "12/main",
- :postgis => "3"
- },
- :styles => {
- :default => {
- :tile_directories => [
- { :name => "/store/tiles/default", :min_zoom => 0, :max_zoom => 19 }
- ]
+ :inet => {
+ :address => "10.5.0.77",
+ :prefix => "16",
+ :gateway => "10.5.0.1",
+ :public_address => "161.53.248.77"
+ }
}
}
}
)
run_list(
- "role[carnet]",
- "role[tile]"
+ "role[carnet]"
)
+++ /dev/null
-name "ridgeback"
-description "Master role applied to ridgeback"
-
-default_attributes(
- :hardware => {
- :ipmi => {
- :excluded_sensors => [19, 20, 21, 22]
- },
- :shm_size => "10g"
- },
- :munin => {
- :plugins => {
- :ipmi_fans => {
- :Fan4 => { :graph => "no", :warning => "0:" },
- :Fan5 => { :graph => "no", :warning => "0:" },
- :Fan6 => { :graph => "no", :warning => "0:" },
- :Fan7CPU1 => { :graph => "no", :warning => "0:" }
- },
- :smart_sda => {
- :smartctl_exit_status => {
- :warning => 8
- }
- },
- :smart_sdb => {
- :smartctl_exit_status => {
- :warning => 8
- }
- }
- }
- },
- :networking => {
- :interfaces => {
- :external_ipv4 => {
- :interface => "eth0",
- :role => :external,
- :family => :inet,
- :address => "31.169.50.10",
- :prefix => "30",
- :gateway => "31.169.50.9"
- }
- }
- },
- :sysfs => {
- :md_tune => {
- :comment => "Tune the md sync performance so as not to kill system performance",
- :parameters => {
- "block/md0/md/sync_speed_min" => "1",
- "block/md0/md/sync_speed_max" => "100000",
- "block/md1/md/sync_speed_min" => "1",
- "block/md1/md/sync_speed_max" => "100000"
- }
- }
- },
- :squid => {
- :version => 4,
- :cache_mem => "8192 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :tilecache => {
- :tile_parent => "oslo.render.openstreetmap.org"
- }
-)
-
-run_list(
- "role[blix-no]",
- "role[geodns]",
- "role[tilecache]"
-)
:max_connections_per_child => 10000
}
},
- :bind => {
- :clients => "ucl"
- },
:dhcpd => {
:first_address => "10.0.15.1",
:last_address => "10.0.15.254"
},
:networking => {
:interfaces => {
- :external_ipv4 => {
+ :external => {
:interface => "eth0.2800",
:role => :external,
- :family => :inet,
- :address => "193.60.236.19"
+ :inet => {
+ :address => "193.60.236.19"
+ }
},
- :internal_ipv4 => {
+ :internal => {
:interface => "eth0.2801",
:role => :internal,
- :family => :inet,
- :address => "10.0.0.3"
+ :inet => {
+ :address => "10.0.0.3"
+ }
}
}
}
"role[gateway]",
"role[foundation]",
"role[stateofthemap]",
- "role[switch2osm]",
"role[blog]",
"role[otrs]",
- "role[donate]",
- "recipe[hot]",
- "recipe[dmca]",
"recipe[dhcpd]"
)
+++ /dev/null
-name "saphira"
-description "Master role applied to saphira"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :external_ipv4 => {
- :interface => "eth0",
- :role => :external,
- :family => :inet,
- :address => "185.73.44.30",
- :prefix => "22",
- :gateway => "185.73.44.1"
- },
- :external_ipv6 => {
- :interface => "eth0",
- :role => :external,
- :family => :inet6,
- :address => "2001:ba8:0:2c1e::",
- :prefix => "64",
- :gateway => "fe80::fcff:ffff:feff:ffff"
- }
- }
- }
-)
-
-run_list(
- "role[jump]",
- "role[geodns]"
-)
+++ /dev/null
-name "sarel"
-description "Master role applied to sarel"
-
-default_attributes(
- :apache => {
- :mpm => "event",
- :event => {
- :min_spare_threads => 50,
- :max_spare_threads => 150,
- :listen_cores_buckets_ratio => 4
- }
- },
- :git => {
- :private_user => "chefrepo",
- :private_group => "chefrepo"
- },
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "enp3s0f0.2801",
- :role => :internal,
- :family => :inet,
- :address => "10.0.0.12"
- },
- :external_ipv4 => {
- :interface => "enp3s0f0.2800",
- :role => :external,
- :family => :inet,
- :address => "193.60.236.20"
- }
- }
- }
-)
-
-run_list(
- "role[ucl]",
- "role[chef-server]",
- "role[chef-repository]",
- "role[letsencrypt]",
- "role[git]",
- "role[dns]",
- "recipe[serverinfo]"
-)
+++ /dev/null
-name "sarkany"
-description "Master role applied to sarkany"
-
-default_attributes(
- :hardware => {
- :shm_size => "8g"
- },
- :networking => {
- :interfaces => {
- :external_ipv4 => {
- :interface => "eth0",
- :role => :external,
- :family => :inet,
- :address => "37.17.173.8",
- :prefix => "24",
- :gateway => "37.17.173.254"
- },
- :external_ipv6 => {
- :interface => "eth0",
- :role => :external,
- :family => :inet6,
- :address => "2001:4c48:2:bf04:250:56ff:fe8f:5c81",
- :prefix => "64",
- :gateway => "fe80::224:14ff:fe84:5000"
- }
- }
- },
- :squid => {
- :version => 4,
- :cache_mem => "6144 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 12800 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 16000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 22400 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 22800 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :nginx => {
- :cache => {
- :proxy => {
- :max_size => "4096M"
- }
- }
- },
- :tilecache => {
- :tile_parent => "budapest.render.openstreetmap.org"
- }
-)
-
-run_list(
- "role[szerverem]",
- "role[tilecache]"
-)
}
}
},
- :hardware => {
- :mcelog => {
- :enabled => false
- }
- },
:networking => {
:interfaces => {
- :external_ipv4 => {
- :interface => "eth0",
- :role => :external,
- :family => :inet,
- :address => "176.31.235.79",
- :prefix => "24",
- :gateway => "176.31.235.254"
- },
- :external_ipv6 => {
+ :external => {
:interface => "eth0",
:role => :external,
- :family => :inet6,
- :address => "2001:41d0:2:fc4f::1",
- :prefix => "64",
- :gateway => "2001:41d0:2:fcff:ff:ff:ff:ff"
- }
- }
- },
- :postgresql => {
- :settings => {
- :defaults => {
- :shared_buffers => "8GB",
- :maintenance_work_mem => "7144MB",
- :effective_cache_size => "16GB"
- }
- }
- },
- :sysctl => {
- :postgres => {
- :comment => "Increase shared memory for postgres",
- :parameters => {
- "kernel.shmmax" => 9 * 1024 * 1024 * 1024,
- "kernel.shmall" => 9 * 1024 * 1024 * 1024 / 4096
- }
- }
- },
- :tile => {
- :database => {
- :cluster => "12/main",
- :postgis => "3"
- },
- :styles => {
- :default => {
- :tile_directories => [
- { :name => "/store/tiles/default", :min_zoom => 0, :max_zoom => 19 }
- ]
+ :inet => {
+ :address => "176.31.235.79",
+ :prefix => "24",
+ :gateway => "176.31.235.254"
+ },
+ :inet6 => {
+ :address => "2001:41d0:2:fc4f::1",
+ :prefix => "64",
+ :gateway => "2001:41d0:2:fcff:ff:ff:ff:ff"
+ }
}
}
}
)
run_list(
- "role[ovh]",
- "role[tile]"
+ "role[ovh]"
)
:ignore => %w[in6]
}
},
- :mcelog => {
- :enabled => false
- },
:modules => [
"it87"
]
+ },
+ :prometheus => {
+ :metrics => {
+ :exim_queue_limit => { :metric => 250 }
+ }
}
)
override_attributes(
:networking => {
+ :dnssec => "false",
:interfaces => {
- :external_ipv4 => {
+ :external => {
:interface => "eth0",
:role => :external,
- :family => :inet,
- :address => "212.110.172.32",
- :prefix => "26",
- :gateway => "212.110.172.1"
- },
- :external_ipv6 => {
- :interface => "eth0",
- :role => :external,
- :family => :inet6,
- :address => "2001:41c9:1:400::32",
- :prefix => "64",
- :gateway => "fe80::1"
+ :inet => {
+ :address => "212.110.172.32",
+ :prefix => "26",
+ :gateway => "212.110.172.1"
+ },
+ :inet6 => {
+ :address => "2001:41c9:1:400::32",
+ :prefix => "64",
+ :gateway => "fe80::1"
+ }
}
- },
- :nameservers => ["1.1.1.1", "1.0.0.1", "2606:4700:4700::1111", "2606:4700:4700::1001"],
- :private_address => "10.0.16.100"
+ }
}
)
run_list(
"role[bytemark]",
- "role[mail]",
"role[lists]",
- "role[subversion]",
- "role[trac]",
- "role[osqa]",
- "role[irc]",
- "recipe[blogs]"
+ "role[osqa]"
)
+++ /dev/null
-name "shruikan"
-description "Master role applied to shruikan"
-
-default_attributes(
- :hardware => {
- :shm_size => "14g"
- },
- :networking => {
- :interfaces => {
- :external_ipv4 => {
- :interface => "ens18",
- :role => :external,
- :family => :inet,
- :address => "45.148.169.51",
- :prefix => "25",
- :gateway => "45.148.169.1"
- },
- :external_ipv6 => {
- :interface => "ens18",
- :role => :external,
- :family => :inet6,
- :address => "2a0a:aa42:56:1000::1",
- :prefix => "48",
- :gateway => "2a0a:aa42:56::1"
- }
- }
- },
- :squid => {
- :version => 4,
- :cache_mem => "10240 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 12800 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 16000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 22400 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 22800 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :nginx => {
- :cache => {
- :proxy => {
- :max_size => "16384M"
- }
- }
- },
- :tilecache => {
- :tile_parent => "netherlands.render.openstreetmap.org"
- }
-)
-
-run_list(
- "role[greenmini]",
- "role[tilecache]"
-)
--- /dev/null
+name "smaug"
+description "Master role applied to smaug"
+
+default_attributes(
+ :networking => {
+ :interfaces => {
+ :internal => {
+ :interface => "bond0",
+ :role => :internal,
+ :inet => {
+ :address => "10.0.64.14"
+ },
+ :bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
+ :slaves => %w[eno1 eno2 eno3 eno4 eno5 eno6]
+ }
+ },
+ :external => {
+ :interface => "bond0.101",
+ :role => :external,
+ :inet => {
+ :address => "184.104.226.110"
+ },
+ :inet6 => {
+ :address => "2001:470:1:b3b::e"
+ }
+ }
+ }
+ }
+)
+
+run_list(
+ "role[equinix-dub]",
+ "role[matomo]"
+)
default_attributes(
:networking => {
:interfaces => {
- :internal_ipv4 => {
+ :internal => {
:interface => "bond0",
:role => :internal,
- :family => :inet,
- :address => "10.0.48.49",
+ :inet => {
+ :address => "10.0.48.49"
+ },
:bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
:slaves => %w[eno1 eno2 eno3 eno4]
}
}
:shared_buffers => "128GB",
:work_mem => "128MB",
:maintenance_work_mem => "2GB",
- :effective_cache_size => "360GB",
- :effective_io_concurrency => "256",
- :random_page_cost => "1.1"
+ :effective_cache_size => "360GB"
}
}
},
)
run_list(
- "role[equinix]",
+ "role[equinix-ams]",
"role[db-master]",
"role[db-backup]"
)
default_attributes(
:networking => {
:interfaces => {
- :internal_ipv4 => {
+ :internal => {
:interface => "eno1.2801",
:role => :internal,
- :family => :inet,
- :address => "10.0.0.4"
+ :inet => {
+ :address => "10.0.0.4"
+ }
}
}
},
:shared_buffers => "128GB",
:work_mem => "128MB",
:maintenance_work_mem => "2GB",
- :effective_cache_size => "360GB",
- :effective_io_concurrency => "256",
- :random_page_cost => "1.1"
+ :effective_cache_size => "360GB"
}
}
},
--- /dev/null
+name "snap-03"
+description "Master role applied to snap-03"
+
+default_attributes(
+ :networking => {
+ :interfaces => {
+ :internal => {
+ :interface => "bond0",
+ :role => :internal,
+ :inet => {
+ :address => "10.0.64.50"
+ },
+ :bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
+ :slaves => %w[enp25s0f0 enp25s0f1]
+ }
+ }
+ }
+ },
+ :postgresql => {
+ :settings => {
+ :defaults => {
+ :shared_buffers => "128GB",
+ :work_mem => "128MB",
+ :maintenance_work_mem => "2GB",
+ :effective_cache_size => "360GB"
+ }
+ }
+ },
+ :sysctl => {
+ :postgres => {
+ :comment => "Increase shared memory for postgres",
+ :parameters => {
+ "kernel.shmmax" => 132 * 1024 * 1024 * 1024,
+ "kernel.shmall" => 132 * 1024 * 1024 * 1024 / 4096
+ }
+ }
+ }
+)
+
+run_list(
+ "role[equinix-dub]",
+ "role[db-slave]"
+)
--- /dev/null
+name "spike-01"
+description "Master role applied to spike-01"
+
+default_attributes(
+ :networking => {
+ :interfaces => {
+ :internal => {
+ :interface => "bond0",
+ :role => :internal,
+ :inet => {
+ :address => "10.0.64.3"
+ },
+ :bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
+ :slaves => %w[eno1 eno2 eno3 eno4 eno49 eno50]
+ }
+ },
+ :external => {
+ :interface => "bond0.101",
+ :role => :external,
+ :inet => {
+ :address => "184.104.226.99"
+ },
+ :inet6 => {
+ :address => "2001:470:1:b3b::3"
+ }
+ }
+ }
+ }
+)
+
+run_list(
+ "role[equinix-dub]",
+ "role[hp-g9]",
+ "role[web-frontend]"
+)
--- /dev/null
+name "spike-02"
+description "Master role applied to spike-02"
+
+default_attributes(
+ :networking => {
+ :interfaces => {
+ :internal => {
+ :interface => "bond0",
+ :role => :internal,
+ :inet => {
+ :address => "10.0.64.4"
+ },
+ :bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
+ :slaves => %w[eno1 eno2 eno3 eno4 eno49 eno50]
+ }
+ },
+ :external => {
+ :interface => "bond0.101",
+ :role => :external,
+ :inet => {
+ :address => "184.104.226.100"
+ },
+ :inet6 => {
+ :address => "2001:470:1:b3b::4"
+ }
+ }
+ }
+ }
+)
+
+run_list(
+ "role[equinix-dub]",
+ "role[hp-g9]",
+ "role[web-frontend]"
+)
--- /dev/null
+name "spike-03"
+description "Master role applied to spike-03"
+
+default_attributes(
+ :networking => {
+ :interfaces => {
+ :internal => {
+ :interface => "bond0",
+ :role => :internal,
+ :inet => {
+ :address => "10.0.64.5"
+ },
+ :bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
+ :slaves => %w[eno1 eno2 eno3 eno4 eno49 eno50]
+ }
+ },
+ :external => {
+ :interface => "bond0.101",
+ :role => :external,
+ :inet => {
+ :address => "184.104.226.101"
+ },
+ :inet6 => {
+ :address => "2001:470:1:b3b::5"
+ }
+ }
+ }
+ }
+)
+
+run_list(
+ "role[equinix-dub]",
+ "role[hp-g9]",
+ "role[web-frontend]"
+)
+++ /dev/null
-name "spike-04"
-description "Master role applied to spike-04"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "bond0",
- :role => :internal,
- :family => :inet,
- :address => "10.0.32.21",
- :bond => {
- :slaves => %w[enp3s0f0 enp3s0f1]
- }
- },
- :external_ipv4 => {
- :interface => "bond0.214",
- :role => :external,
- :family => :inet,
- :address => "89.16.162.21"
- },
- :external_ipv6 => {
- :interface => "bond0.214",
- :role => :external,
- :family => :inet6,
- :address => "2001:41c9:2:d6::21"
- }
- }
- }
-)
-
-run_list(
- "role[bytemark]",
- "role[web-frontend]"
- # "role[web-gpximport]",
- # "role[web-statistics]",
- # "role[web-cleanup]"
-)
+++ /dev/null
-name "spike-05"
-description "Master role applied to spike-05"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "bond0",
- :role => :internal,
- :family => :inet,
- :address => "10.0.32.22",
- :bond => {
- :slaves => %w[enp3s0f0 enp3s0f1]
- }
- },
- :external_ipv4 => {
- :interface => "bond0.214",
- :role => :external,
- :family => :inet,
- :address => "89.16.162.22"
- },
- :external_ipv6 => {
- :interface => "bond0.214",
- :role => :external,
- :family => :inet6,
- :address => "2001:41c9:2:d6::22"
- }
- }
- }
-)
-
-run_list(
- "role[bytemark]",
- "role[web-frontend]"
-)
default_attributes(
:networking => {
:interfaces => {
- :internal_ipv4 => {
+ :internal => {
:interface => "bond0",
:role => :internal,
- :family => :inet,
- :address => "10.0.48.11",
+ :inet => {
+ :address => "10.0.48.11"
+ },
:bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
:slaves => %w[eno1 eno2]
}
},
- :external_ipv4 => {
- :interface => "bond0.2",
+ :external => {
+ :interface => "bond0.3",
:role => :external,
- :family => :inet,
- :address => "130.117.76.11"
- },
- :external_ipv6 => {
- :interface => "bond0.2",
- :role => :external,
- :family => :inet6,
- :address => "2001:978:2:2C::172:B"
+ :inet => {
+ :address => "184.104.179.139"
+ },
+ :inet6 => {
+ :address => "2001:470:1:fa1::b"
+ }
}
}
}
)
run_list(
- "role[equinix]",
+ "role[equinix-ams]",
"role[hp-g9]",
"role[web-frontend]",
"role[web-statistics]",
default_attributes(
:networking => {
:interfaces => {
- :internal_ipv4 => {
+ :internal => {
:interface => "bond0",
:role => :internal,
- :family => :inet,
- :address => "10.0.48.12",
+ :inet => {
+ :address => "10.0.48.12"
+ },
:bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
:slaves => %w[eno1 eno2]
}
},
- :external_ipv4 => {
- :interface => "bond0.2",
+ :external => {
+ :interface => "bond0.3",
:role => :external,
- :family => :inet,
- :address => "130.117.76.12"
- },
- :external_ipv6 => {
- :interface => "bond0.2",
- :role => :external,
- :family => :inet6,
- :address => "2001:978:2:2C::172:C"
+ :inet => {
+ :address => "184.104.179.140"
+ },
+ :inet6 => {
+ :address => "2001:470:1:fa1::c"
+ }
}
}
}
)
run_list(
- "role[equinix]",
+ "role[equinix-ams]",
"role[hp-g9]",
"role[web-frontend]"
)
default_attributes(
:networking => {
:interfaces => {
- :internal_ipv4 => {
+ :internal => {
:interface => "bond0",
:role => :internal,
- :family => :inet,
- :address => "10.0.48.13",
+ :inet => {
+ :address => "10.0.48.13"
+ },
:bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
:slaves => %w[eno1 eno2]
}
},
- :external_ipv4 => {
- :interface => "bond0.2",
+ :external => {
+ :interface => "bond0.3",
:role => :external,
- :family => :inet,
- :address => "130.117.76.13"
- },
- :external_ipv6 => {
- :interface => "bond0.2",
- :role => :external,
- :family => :inet6,
- :address => "2001:978:2:2C::172:D"
+ :inet => {
+ :address => "184.104.179.141"
+ },
+ :inet6 => {
+ :address => "2001:470:1:fa1::d"
+ }
}
}
}
)
run_list(
- "role[equinix]",
+ "role[equinix-ams]",
"role[hp-g9]",
"role[web-frontend]"
)
description "Role applied to State of the Map servers"
run_list(
- "recipe[stateofthemap]"
+ "recipe[stateofthemap]",
+ "recipe[stateofthemap::wordpress]"
)
default_attributes(
:networking => {
:interfaces => {
- :external_ipv4 => {
+ :external => {
:interface => "bond0",
:role => :external,
- :family => :inet,
- :address => "140.211.167.99",
+ :inet => {
+ :address => "140.211.167.99"
+ },
+ :inet6 => {
+ :address => "2605:bc80:3010:700::8cd3:a763"
+ },
:bond => {
:slaves => %w[eno1 eno2 eno3 eno4 eno49 eno50]
}
- },
- :external_ipv6 => {
- :interface => "bond0",
- :role => :external,
- :family => :inet6,
- :address => "2605:bc80:3010:700::8cd3:a763"
}
},
:private_address => "10.0.16.200"
- },
- :tilecache => {
- :tile_parent => "corvallis.render.openstreetmap.org"
}
)
},
:networking => {
:interfaces => {
- :external_ipv4 => {
+ :external => {
:interface => "bond0",
:role => :external,
- :family => :inet,
- :address => "140.211.167.100",
+ :inet => {
+ :address => "140.211.167.100"
+ },
+ :inet6 => {
+ :address => "2605:bc80:3010:700::8cd3:a764"
+ },
:bond => {
:slaves => %w[eno1 eno2 eno3 eno4 eno49 eno50]
}
- },
- :external_ipv6 => {
- :interface => "bond0",
- :role => :external,
- :family => :inet6,
- :address => "2605:bc80:3010:700::8cd3:a764"
}
}
},
:postgresql => {
- :versions => ["12"],
+ :versions => ["15"],
:settings => {
:defaults => {
:work_mem => "300MB",
- :maintenance_work_mem => "10GB",
- :random_page_cost => "1.5",
- :effective_cache_size => "60GB",
:fsync => "on",
:effective_io_concurrency => "100"
}
},
:nominatim => {
:state => "standalone",
- :enable_backup => false,
- :enable_git_updates => true,
- :dbadmins => %w[lonvia tomh],
- :dbcluster => "12/main",
- :postgis => "2.5",
- :flatnode_file => "/ssd/nominatim/nodes.store",
- :logdir => "/ssd/nominatim/log",
- :fpm_pools => {
- "nominatim.openstreetmap.org" => {
- :max_children => 100
- }
- },
- :tablespaces => {
- "dosm" => "/ssd/tablespaces/dosm",
- "iosm" => "/ssd/tablespaces/iosm",
- "dplace" => "/ssd/tablespaces/dplace",
- "iplace" => "/ssd/tablespaces/iplace",
- "daddress" => "/ssd/tablespaces/daddress",
- "iaddress" => "/ssd/tablespaces/iaddress",
- "dsearch" => "/ssd/tablespaces/dsearch",
- "isearch" => "/ssd/tablespaces/isearch",
- "daux" => "/ssd/tablespaces/daux",
- "iaux" => "/ssd/tablespaces/iaux"
- }
+ :dbcluster => "15/main",
+ :postgis => "3",
+ :flatnode_file => "/srv/nominatim.openstreetmap.org/planet-project/nodes.store",
+ :api_flavour => "python",
+ :api_workers => 19,
+ :api_pool_size => 7
}
)
+++ /dev/null
-name "strato"
-description "Role applied to all servers at Strato"
-
-default_attributes(
- :hosted_by => "Strato",
- :location => "Germany"
-)
-
-override_attributes(
- :networking => {
- :nameservers => ["85.214.7.22", "81.169.163.106"]
- },
- :ntp => {
- :servers => ["0.de.pool.ntp.org", "1.de.pool.ntp.org", "europe.pool.ntp.org"]
- }
-)
-
-run_list(
- "role[de]"
-)
+++ /dev/null
-name "supermicro-x8dtt-h"
-description "Role applied to all Supermicro X8DTT-H machines"
-
-default_attributes(
- :hardware => {
- :watchdog => "w83627hf_wdt"
- }
-)
+++ /dev/null
-name "szerverem"
-description "Role applied to all servers at szerverem.hu"
-
-default_attributes(
- :hosted_by => "szerverem.hu",
- :location => "Budapest, Hungary"
-)
-
-override_attributes(
- :ntp => {
- :servers => ["0.hu.pool.ntp.org", "1.hu.pool.ntp.org", "europe.pool.ntp.org"]
- }
-)
-
-run_list(
- "role[hu]"
-)
+++ /dev/null
-name "tabaluga"
-description "Master role applied to tabaluga"
-
-default_attributes(
- :dhcpd => {
- :first_address => "10.0.62.1",
- :last_address => "10.0.62.254"
- },
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "bond0",
- :role => :internal,
- :family => :inet,
- :address => "10.0.48.14",
- :bond => {
- :slaves => %w[eno1 eno2]
- }
- },
- :external_ipv4 => {
- :interface => "bond0.2",
- :role => :external,
- :family => :inet,
- :address => "130.117.76.14"
- },
- :external_ipv6 => {
- :interface => "bond0.2",
- :role => :external,
- :family => :inet6,
- :address => "2001:978:2:2C::172:E"
- }
- }
- }
-)
-
-run_list(
- "role[equinix]",
- "role[hp-g9]",
- "role[wiki]",
- "recipe[dhcpd]"
-)
:passenger => {
:max_pool_size => 50
},
- :planet => {
- :current => {
- :jobs => {
- :taginfo => {
- :command => "/usr/local/bin/taginfo-update",
- :user => "taginfo"
- }
- }
- }
- },
:taginfo => {
:sites => [
{
)
run_list(
- "role[planet-current]",
"recipe[taginfo]"
)
+++ /dev/null
-name "takhisis"
-description "Master role applied to takhisis"
-
-default_attributes(
- :hardware => {
- :shm_size => "14g"
- },
- :networking => {
- :interfaces => {
- :external_ipv4 => {
- :interface => "ens18",
- :role => :external,
- :family => :inet,
- :address => "31.3.110.20",
- :prefix => "24",
- :gateway => "31.3.110.1"
- },
- :external_ipv6 => {
- :interface => "ens18",
- :role => :external,
- :family => :inet6,
- :address => "2a03:7900:111:0:31:3:110:20",
- :prefix => "64",
- :gateway => "fe80::225:90ff:fe5d:c1e1"
- }
- }
- },
- :squid => {
- :version => 4,
- :cache_mem => "10240 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :nginx => {
- :cache => {
- :proxy => {
- :directory => "/store/nginx-cache/proxy-cache",
- :max_size => "65536M"
- }
- }
- },
- :tilecache => {
- :tile_parent => "netherlands.render.openstreetmap.org"
- }
-)
-
-run_list(
- "role[tuxis]",
- "role[tilecache]"
-)
+++ /dev/null
-name "teraswitch"
-description "Role applied to all servers at TeraSwitch Networks"
-
-default_attributes(
- :accounts => {
- :users => {
- :sysadmin => { :status => :administrator }
- }
- },
- :hosted_by => "TeraSwitch Networks",
- :location => "Pittsburgh, Pennsylvania",
- :timezone => "EST5EDT"
-)
-
-override_attributes(
- :ntp => {
- :servers => ["0.us.pool.ntp.org", "1.us.pool.ntp.org", "north-america.pool.ntp.org"]
- }
-)
-
-run_list(
- "role[us]"
-)
+++ /dev/null
-name "thorn-02"
-description "Master role applied to thorn-02"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "bond0",
- :role => :internal,
- :family => :inet,
- :address => "10.0.48.52",
- :bond => {
- :slaves => %w[eth0 eth1]
- }
- }
- }
- }
-)
-
-run_list(
- "role[equinix]"
-)
+++ /dev/null
-name "thorn-03"
-description "Master role applied to thorn-03"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "bond0",
- :role => :internal,
- :family => :inet,
- :address => "10.0.48.53",
- :bond => {
- :slaves => %w[eth0 eth1]
- }
- }
- }
- }
-)
-
-run_list(
- "role[equinix]"
-)
+++ /dev/null
-name "thorn-04"
-description "Master role applied to thorn-04"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "bond0",
- :role => :internal,
- :family => :inet,
- :address => "10.0.32.41",
- :bond => {
- :slaves => %w[enp3s0f0 enp3s0f1]
- }
- }
- }
- }
-)
-
-run_list(
- "role[bytemark]"
-)
+++ /dev/null
-name "thorn-05"
-description "Master role applied to thorn-05"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "bond0",
- :role => :internal,
- :family => :inet,
- :address => "10.0.32.42",
- :bond => {
- :slaves => %w[enp3s0f0 enp3s0f1]
- }
- }
- }
- }
-)
-
-run_list(
- "role[bytemark]"
-)
+++ /dev/null
-name "tiamat-00"
-description "Master role applied to tiamat-00"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "enp1s0.2801",
- :role => :internal,
- :family => :inet,
- :address => "10.0.0.40"
- },
- :external_ipv4 => {
- :interface => "enp1s0.2800",
- :role => :external,
- :family => :inet,
- :address => "193.60.236.40"
- }
- }
- }
-)
-
-run_list(
- "role[ucl]",
- "role[supermicro-x8dtt-h]",
- "role[crm]"
-)
+++ /dev/null
-name "tiamat-01"
-description "Master role applied to tiamat-01"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "enp1s0.2801",
- :role => :internal,
- :family => :inet,
- :address => "10.0.0.41"
- },
- :external_ipv4 => {
- :interface => "enp1s0.2800",
- :role => :external,
- :family => :inet,
- :address => "193.60.236.41"
- }
- }
- }
-)
-
-run_list(
- "role[ucl]",
- "role[supermicro-x8dtt-h]"
-)
+++ /dev/null
-name "tiamat-02"
-description "Master role applied to tiamat-02"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "enp1s0.2801",
- :role => :internal,
- :family => :inet,
- :address => "10.0.0.42"
- },
- :external_ipv4 => {
- :interface => "enp1s0.2800",
- :role => :external,
- :family => :inet,
- :address => "193.60.236.42"
- }
- }
- }
-)
-
-run_list(
- "role[ucl]",
- "role[supermicro-x8dtt-h]"
-)
+++ /dev/null
-name "tiamat-03"
-description "Master role applied to tiamat-03"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "enp1s0.2801",
- :role => :internal,
- :family => :inet,
- :address => "10.0.0.43"
- },
- :external_ipv4 => {
- :interface => "enp1s0.2800",
- :role => :external,
- :family => :inet,
- :address => "193.60.236.43"
- }
- }
- }
-)
-
-run_list(
- "role[ucl]",
- "role[supermicro-x8dtt-h]"
-)
+++ /dev/null
-name "tiamat-10"
-description "Master role applied to tiamat-10"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "enp1s0.2801",
- :role => :internal,
- :family => :inet,
- :address => "10.0.0.44"
- },
- :external_ipv4 => {
- :interface => "enp1s0.2800",
- :role => :external,
- :family => :inet,
- :address => "193.60.236.44"
- }
- }
- }
-)
-
-run_list(
- "role[ucl]",
- "role[supermicro-x8dtt-h]"
-)
+++ /dev/null
-name "tiamat-11"
-description "Master role applied to tiamat-11"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "enp1s0.2801",
- :role => :internal,
- :family => :inet,
- :address => "10.0.0.45"
- },
- :external_ipv4 => {
- :interface => "enp1s0.2800",
- :role => :external,
- :family => :inet,
- :address => "193.60.236.45"
- }
- }
- }
-)
-
-run_list(
- "role[ucl]",
- "role[supermicro-x8dtt-h]"
-)
+++ /dev/null
-name "tiamat-12"
-description "Master role applied to tiamat-12"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "enp1s0.2801",
- :role => :internal,
- :family => :inet,
- :address => "10.0.0.46"
- },
- :external_ipv4 => {
- :interface => "enp1s0.2800",
- :role => :external,
- :family => :inet,
- :address => "193.60.236.46"
- }
- }
- }
-)
-
-run_list(
- "role[ucl]",
- "role[supermicro-x8dtt-h]"
-)
+++ /dev/null
-name "tiamat-13"
-description "Master role applied to tiamat-13"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "enp1s0.2801",
- :role => :internal,
- :family => :inet,
- :address => "10.0.0.47"
- },
- :external_ipv4 => {
- :interface => "enp1s0.2800",
- :role => :external,
- :family => :inet,
- :address => "193.60.236.47"
- }
- }
- }
-)
-
-run_list(
- "role[ucl]",
- "role[supermicro-x8dtt-h]"
-)
+++ /dev/null
-name "tiamat-20"
-description "Master role applied to tiamat-20"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "enp1s0.2801",
- :role => :internal,
- :family => :inet,
- :address => "10.0.0.48"
- },
- :external_ipv4 => {
- :interface => "enp1s0.2800",
- :role => :external,
- :family => :inet,
- :address => "193.60.236.48"
- }
- }
- }
-)
-
-run_list(
- "role[ucl]",
- "role[supermicro-x8dtt-h]"
-)
+++ /dev/null
-name "tiamat-21"
-description "Master role applied to tiamat-21"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "enp1s0.2801",
- :role => :internal,
- :family => :inet,
- :address => "10.0.0.49"
- },
- :external_ipv4 => {
- :interface => "enp1s0.2800",
- :role => :external,
- :family => :inet,
- :address => "193.60.236.49"
- }
- }
- }
-)
-
-run_list(
- "role[ucl]",
- "role[supermicro-x8dtt-h]"
-)
+++ /dev/null
-name "tiamat-22"
-description "Master role applied to tiamat-22"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "enp1s0.2801",
- :role => :internal,
- :family => :inet,
- :address => "10.0.0.50"
- },
- :external_ipv4 => {
- :interface => "enp1s0.2800",
- :role => :external,
- :family => :inet,
- :address => "193.60.236.50"
- }
- }
- }
-)
-
-run_list(
- "role[ucl]",
- "role[supermicro-x8dtt-h]"
-)
+++ /dev/null
-name "tiamat-23"
-description "Master role applied to tiamat-23"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "enp1s0.2801",
- :role => :internal,
- :family => :inet,
- :address => "10.0.0.51"
- },
- :external_ipv4 => {
- :interface => "enp1s0.2800",
- :role => :external,
- :family => :inet,
- :address => "193.60.236.51"
- }
- }
- }
-)
-
-run_list(
- "role[ucl]",
- "role[supermicro-x8dtt-h]"
-)
default_attributes(
:accounts => {
:users => {
+ :pnorman => { :status => :administrator },
:tile => {
- :members => [:jburgess, :tomh]
+ :members => [:jburgess, :tomh, :pnorman]
}
}
},
:apache => {
:mpm => "event",
:timeout => 60,
+ :evasive => {
+ :enable => false
+ },
:event => {
- :server_limit => 60,
- :max_request_workers => 1200,
:threads_per_child => 20,
:min_spare_threads => 300,
- :max_spare_threads => 1200,
:max_connections_per_child => 0,
:async_request_worker_factor => 4,
- :listen_cores_buckets_ratio => 6
- }
- },
- :munin => {
- :plugins => {
- :renderd_processed => {
- :graph_order => "reqPrio req reqLow dirty reqBulk dropped",
- :reqPrio => { :draw => "AREA" },
- :req => { :draw => "STACK" }
- }
+ :listen_cores_buckets_ratio => 8
}
},
:postgresql => {
:settings => {
:defaults => {
:max_connections => "250",
- :temp_buffers => "32MB",
+ :shared_buffers => "16GB",
:work_mem => "128MB",
+ :maintenance_work_mem => "8GB",
:max_parallel_workers_per_gather => "0",
+ :wal_level => "minimal",
:wal_buffers => "1024kB",
:wal_writer_delay => "500ms",
+ :checkpoint_timeout => "60min",
:commit_delay => "10000",
- :checkpoint_segments => "60",
- :max_wal_size => "2880MB",
- :random_page_cost => "1.1",
+ :max_wal_size => "10GB",
+ :max_wal_senders => "0",
:jit => "off",
:track_activity_query_size => "16384",
:autovacuum_vacuum_scale_factor => "0.05",
"net.core.somaxconn" => 10000
}
},
- :kernel_scheduler_tune => {
- :comment => "Tune kernel scheduler preempt",
+ :network_conntrack_time_wait => {
+ :comment => "Only track completed connections for 30 seconds",
:parameters => {
- "kernel.sched_min_granularity_ns" => 10000000,
- "kernel.sched_wakeup_granularity_ns" => 15000000
+ "net.netfilter.nf_conntrack_tcp_timeout_time_wait" => "30"
+ }
+ },
+ :network_conntrack_max => {
+ :comment => "Increase max number of connections tracked",
+ :parameters => {
+ "net.netfilter.nf_conntrack_max" => "524288"
}
},
:no_tcp_slow_start => {
"net.core.default_qdisc" => "fq",
"net.ipv4.tcp_congestion_control" => "bbr"
}
- },
+ }
},
:tile => {
:database => {
:styles => {
:default => {
:repository => "https://github.com/gravitystorm/openstreetmap-carto.git",
- :revision => "v5.3.1",
+ :revision => "v5.8.0",
+ :fonts_script => "/srv/tile.openstreetmap.org/styles/default/scripts/get-fonts.sh",
:max_zoom => 19
}
}
+++ /dev/null
-name "tilecache"
-description "Role applied to all tile cache servers"
-
-default_attributes(
- :accounts => {
- :groups => {
- :proxy => {
- :members => [:tomh, :grant, :matt, :jburgess]
- }
- }
- },
- :nginx => {
- :access_log => false
- },
- :sysctl => {
- :sockets => {
- :comment => "Increase size of connection queue",
- :parameters => {
- "net.core.somaxconn" => 10000
- }
- },
- :network_conntrack_time_wait => {
- :comment => "Only track completed connections for 30 seconds",
- :parameters => {
- "net.netfilter.nf_conntrack_tcp_timeout_time_wait" => "30"
- }
- },
- :network_conntrack_max => {
- :comment => "Increase max number of connections tracked",
- :parameters => {
- "net.netfilter.nf_conntrack_max" => "524288"
- }
- },
- :network_local_port_range => {
- :comment => "Increase available local port range",
- :parameters => {
- "net.ipv4.ip_local_port_range" => "1024\t65535"
- }
- },
- :network_tcp_timewait_reuse => {
- :comment => "Allow tcp timewait reuse",
- :parameters => {
- "net.ipv4.tcp_tw_reuse" => 1
- }
- },
- :squid_swappiness => {
- :comment => "Prefer not to swapout to free memory",
- :parameters => {
- "vm.swappiness" => "1"
- }
- },
- :sched_wakeup => {
- :comment => "Tune scheduler",
- :parameters => {
- "kernel.sched_min_granularity_ns" => "10000000",
- "kernel.sched_wakeup_granularity_ns" => "15000000"
- }
- }
- },
- :tools => {
- :cron => {
- :load => {
- :nice => 19,
- :io_scheduling_class => "best-effort",
- :io_scheduling_priority => 7
- }
- }
- }
-)
-
-run_list(
- "recipe[tilecache]"
-)
+++ /dev/null
-name "toothless"
-description "Master role applied to toothless"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :external_ipv4 => {
- :interface => "eth0",
- :role => :external,
- :family => :inet,
- :address => "185.73.44.167",
- :prefix => "22",
- :gateway => "185.73.44.1"
- },
- :external_ipv6 => {
- :interface => "eth0",
- :role => :external,
- :family => :inet6,
- :address => "2001:ba8:0:2ca7::",
- :prefix => "64",
- :gateway => "fe80::fcff:ffff:feff:ffff"
- }
- }
- }
-)
-
-run_list(
- "role[jump]"
-)
+++ /dev/null
-name "trogdor"
-description "Master role applied to trogdor"
-
-default_attributes(
- :hardware => {
- :shm_size => "14g"
- },
- :networking => {
- :interfaces => {
- :external_ipv4 => {
- :interface => "eth0",
- :role => :external,
- :family => :inet,
- :address => "134.90.146.26",
- :prefix => "30",
- :gateway => "134.90.146.25"
- }
- }
- },
- :sysfs => {
- :md_tune => {
- :comment => "Tune the md sync performance so as not to kill system performance",
- :parameters => {
- "block/md0/md/sync_speed_min" => "1",
- "block/md0/md/sync_speed_max" => "100000",
- "block/md1/md/sync_speed_min" => "1",
- "block/md1/md/sync_speed_max" => "100000"
- }
- }
- },
- :squid => {
- :version => 4,
- :cache_mem => "10240 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :nginx => {
- :cache => {
- :proxy => {
- :max_size => "131072M"
- }
- }
- },
- :tilecache => {
- :tile_parent => "netherlands.render.openstreetmap.org"
- }
-)
-
-run_list(
- "role[blix-nl]",
- "role[tilecache]"
-)
+++ /dev/null
-name "tuxis"
-description "Role applied to all servers at Tuxis"
-
-default_attributes(
- :hosted_by => "Tuxis",
- :location => "Ede, Netherlands"
-)
-
-override_attributes(
- :networking => {
- :nameservers => ["2a03:7900:2:0:31:3:104:61", "2a03:7900:2:0:31:3:104:62"]
- },
- :ntp => {
- :servers => ["0.nl.pool.ntp.org", "1.nl.pool.ntp.org", "europe.pool.ntp.org"]
- }
-)
-
-run_list(
- "role[nl]"
-)
+++ /dev/null
-name "tyan-s7010"
-description "Role applied to machines using the Tyan S7010 motherboard"
-
-default_attributes(
- :hardware => {
- :hwmon => {
- "i2c_0_0_002f" => {
- :ignore => %w[fan3 fan4 fan5 fan6 fan7 fan8 fan9 fan10 fan11 fan12]
- }
- },
- :ipmi => {
- :excluded_sensors => [13, 14, 15, 16, 17, 18, 19, 20]
- },
- :modules => %w[i2c_i801 jc42 w83793],
- :sensors => {
- "jc42-*" => {
- :temps => {
- "temp1" => { :max => 75 }
- }
- },
- "w83793-i2c-*-2f" => {
- :volts => {
- "in0" => { :min => 0.696, :max => 1.424 },
- "in1" => { :min => 0.696, :max => 1.424 },
- "in5" => { :min => 2.992, :max => 3.536 },
- "in9" => { :min => 2.608, :max => 3.536 }
- },
- :fans => {
- "fan1" => { :min => 1500 },
- "fan2" => { :min => 1500 },
- "fan3" => { :ignore => true },
- "fan4" => { :ignore => true },
- "fan5" => { :ignore => true },
- "fan6" => { :ignore => true },
- "fan7" => { :ignore => true },
- "fan8" => { :ignore => true },
- "fan9" => { :ignore => true },
- "fan10" => { :ignore => true },
- "fan11" => { :ignore => true },
- "fan12" => { :ignore => true }
- },
- :temps => {
- "temp5" => { :max => 78, :max_hyst => 73 },
- "temp6" => { :max => 78, :max_hyst => 73 }
- }
- }
- }
- },
- :munin => {
- :plugins => {
- :ipmi_fans => {
- :Sys3Front1 => { :graph => "no", :warning => "0:" },
- :Sys4Front2 => { :graph => "no", :warning => "0:" },
- :Sys5Rear1 => { :graph => "no", :warning => "0:" },
- :Sys6 => { :graph => "no", :warning => "0:" },
- :Sys7 => { :graph => "no", :warning => "0:" },
- :Sys8 => { :graph => "no", :warning => "0:" },
- :Sys9 => { :graph => "no", :warning => "0:" },
- :Sys10 => { :graph => "no", :warning => "0:" }
- },
- :ipmi_temp => {
- :CPU0belowTmax => { :critical => "10:" },
- :CPU1belowTmax => { :critical => "10:" }
- },
- :sensors_volt => {
- "VCoreA" => { :warning => "0.70:1.42", :critical => "0.70:1.42" },
- "VCoreB" => { :warning => "0.70:1.42", :critical => "0.70:1.42" },
- "in2" => { :warning => "0.00:2.05", :critical => "0.00:2.05" },
- "in3" => { :warning => "0.00:4.08", :critical => "0.00:4.08" },
- "in4" => { :warning => "0.00:4.08", :critical => "0.00:4.08" },
- "in5" => { :warning => "2.99:3.54", :critical => "2.99:3.54" },
- "in6" => { :warning => "0.00:2.04", :critical => "0.00:2.04" },
- "+5V" => { :warning => "4.52:5.50", :critical => "4.52:5.50" },
- "5VSB" => { :warning => "4.52:5.50", :critical => "4.52:5.50" },
- "Vbat" => { :warning => "2.70:3.30", :critical => "2.70:3.30" }
- }
- }
- }
-)
override_attributes(
:networking => {
- :nameservers => ["10.0.0.3", "1.1.1.1", "1.0.0.1"],
+ :nameservers => ["10.0.0.3", "8.8.8.8", "8.8.4.4"],
:search => ["ucl.openstreetmap.org", "openstreetmap.org"]
},
:ntp => {
--- /dev/null
+name "umu"
+description "Role applied to all servers at Umeå University"
+
+default_attributes(
+ :accounts => {
+ :users => {
+ :maswan => { :status => :administrator }
+ }
+ },
+ :hosted_by => "Academic Computer Club, Umeå University",
+ :location => "Umeå, Sweden"
+)
+
+override_attributes(
+ :networking => {
+ :nameservers => ["130.239.18.251", "130.239.18.252", "130.239.1.90"]
+ },
+ :ntp => {
+ :servers => ["0.se.pool.ntp.org", "1.se.pool.ntp.org", "europe.pool.ntp.org"]
+ }
+)
+
+run_list(
+ "role[se]"
+)
+++ /dev/null
-name "urmel"
-description "Master role applied to urmel"
-
-default_attributes(
- :networking => {
- :interfaces => {
- :internal_ipv4 => {
- :interface => "eth0.2801",
- :role => :internal,
- :family => :inet,
- :address => "10.0.0.6"
- },
- :external_ipv4 => {
- :interface => "eth0.2800",
- :role => :external,
- :family => :inet,
- :address => "193.60.236.21"
- }
- }
- }
-)
-
-run_list(
- "role[ucl]",
- "role[hp-dl360-g6]",
- "role[munin]"
-)
+++ /dev/null
-name "utelecom"
-description "Role applied to all servers at Ukrainian Telecommunication Group"
-
-default_attributes(
- :hosted_by => "Ukrainian Telecommunication Group",
- :location => "Kiev, Ukraine"
-)
-
-override_attributes(
- :ntp => {
- :servers => ["0.ua.pool.ntp.org", "1.ua.pool.ntp.org", "europe.pool.ntp.org"]
- }
-)
-
-run_list(
- "role[ua]"
-)
--- /dev/null
+name "vhagar"
+description "Master role applied to vhagar"
+
+default_attributes(
+ :networking => {
+ :interfaces => {
+ :internal => {
+ :interface => "bond0",
+ :role => :internal,
+ :inet => {
+ :address => "10.0.48.5"
+ },
+ :bond => {
+ :mode => "802.3ad",
+ :lacprate => "fast",
+ :xmithashpolicy => "layer3+4",
+ :slaves => %w[eno1 eno2 eno3 eno4 eno5 eno6]
+ }
+ },
+ :external => {
+ :interface => "bond0.3",
+ :role => :external,
+ :inet => {
+ :address => "184.104.179.133"
+ },
+ :inet6 => {
+ :address => "2001:470:1:fa1::5"
+ }
+ }
+ }
+ },
+ :nominatim => {
+ :state => "standalone",
+ :dbcluster => "15/main",
+ :flatnode_file => "/srv/nominatim.openstreetmap.org/planet-project/nodes.store",
+ :api_flavour => "python",
+ :api_workers => 24,
+ :api_pool_size => 8
+ }
+)
+
+run_list(
+ "role[equinix-ams]",
+ "role[nominatim]"
+)
+++ /dev/null
-name "vipertooth"
-description "Master role applied to vipertooth"
-
-default_attributes(
- :hardware => {
- :shm_size => "18g"
- },
- :location => "Kiev, Ukraine",
- :networking => {
- :interfaces => {
- :external_ipv4 => {
- :interface => "ens160",
- :role => :external,
- :family => :inet,
- :address => "176.122.99.101",
- :prefix => "26",
- :gateway => "176.122.99.126"
- },
- :external_ipv6 => {
- :interface => "ens160",
- :role => :external,
- :family => :inet6,
- :address => "2001:67c:2d40::65",
- :prefix => "64",
- :gateway => "2001:67c:2d40::fffe"
- }
- }
- },
- :squid => {
- :version => 4,
- :cache_mem => "16384 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :tilecache => {
- :tile_parent => "kiev.render.openstreetmap.org"
- }
-)
-
-run_list(
- "role[utelecom]",
- "role[tilecache]"
-)
+++ /dev/null
-name "viserion"
-description "Master role applied to viserion"
-
-default_attributes(
- :accounts => {
- :users => {
- :anovak => { :status => :administrator }
- }
- },
- :hardware => {
- :shm_size => "36g"
- },
- :location => "Pula, Croatia",
- :munin => {
- :allow => ["193.198.233.210"]
- },
- :networking => {
- :interfaces => {
- :external_ipv4 => {
- :interface => "eth0",
- :role => :external,
- :family => :inet,
- :address => "193.198.233.211",
- :prefix => "29",
- :gateway => "193.198.233.209"
- },
- :external_ipv6 => {
- :interface => "eth0",
- :role => :external,
- :family => :inet6,
- :address => "2001:b68:4cff:3::3",
- :prefix => "64",
- :gateway => "2001:b68:4cff:3::1"
- }
- }
- },
- :squid => {
- :version => 4,
- :cache_mem => "32768 MB",
- :cache_dir => [
- "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
- "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
- "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
- "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
- ]
- },
- :tilecache => {
- :tile_parent => "pula.render.openstreetmap.org"
- }
-)
-
-run_list(
- "role[carnet]",
- "role[tilecache]"
-)
+++ /dev/null
-name "web-backend"
-description "Role applied to all web/api backend servers"
-
-default_attributes(
- :apache => {
- :mpm => "event",
- :event => {
- :max_connections_per_child => 10000,
- :async_request_worker_factor => 4
- }
- },
- :logstash => {
- :forwarder => {
- "filebeat.prospectors" => [
- { "input_type" => "log", "paths" => ["/var/log/apache2/access.log"], "fields" => { "type" => "apache" } },
- { "input_type" => "log", "paths" => ["/var/log/web/rails-logstash.log"], "fields" => { "type" => "rails" } }
- ]
- }
- },
- :memcached => {
- :memory_limit => 4096
- },
- :passenger => {
- :max_pool_size => 12
- }
-)
-
-run_list(
- "role[web]",
- "role[logstash-forwarder]",
- "recipe[web::backend]"
-)
},
:logstash => {
:forwarder => {
- "filebeat.prospectors" => [
- { "input_type" => "log", "paths" => ["/var/log/apache2/access.log"], "fields" => { "type" => "apache" } },
- { "input_type" => "log", "paths" => ["/var/log/web/rails-logstash.log"], "fields" => { "type" => "rails" } }
+ "filebeat.inputs" => [
+ { "type" => "filestream", "id" => "apache", "paths" => ["/var/log/apache2/access.log"], "fields" => { "type" => "apache" }, "fields_under_root" => true },
+ { "type" => "filestream", "id" => "rails", "paths" => ["/var/log/web/rails-logstash.log"], "fields" => { "type" => "rails" }, "fields_under_root" => true }
]
}
},
:memcached => {
- :memory_limit => 4096
+ :memory_limit => 8192
+ },
+ :networking => {
+ :firewall => {
+ :http_rate_limit => "s:5/sec:30"
+ }
},
:passenger => {
:max_pool_size => 50
:messages => {
:comment => "messages.openstreetmap.org",
:domains => ["messages.openstreetmap.org"],
- :command => "/usr/local/bin/passenger-ruby /srv/www.openstreetmap.org/rails/script/deliver-message $local_part",
+ :local_parts => ["${lookup{$local_part}lsearch*,ret=key{/etc/exim4/detaint}}"],
+ :command => "/usr/local/bin/deliver-message $local_part_data",
:user => "rails",
:group => "rails",
:home_directory => "/srv/www.openstreetmap.org/rails",
:path => "/bin:/usr/bin:/usr/local/bin",
- :environment => {
- "RAILS_ENV" => "production"
- }
+ :case_sensitive => true
}
}
}
+++ /dev/null
-name "web-storage"
-description "Base role applied to all web/api storage servers"
-
-default_attributes(
- :accounts => {
- :users => {
- :rails => { :status => :role }
- }
- }
-)
-
-run_list(
- "recipe[nfs::server]"
-)
:max_request_workers => 800,
:threads_per_child => 50,
:max_connections_per_child => 10000
+ },
+ :evasive => {
+ :page_count => 250,
+ :site_count => 500
}
},
:elasticsearch => {
- :version => "6.x",
+ :version => "7.x",
:cluster => {
:name => "wiki"
}
]
},
:memcached => {
- :memory_limit => 1024,
+ :memory_limit => 4096,
:connection_limit => 8192,
- :chunk_growth_factor => 1.05,
- :min_item_size => 5
+ :chunk_growth_factor => 1.25,
+ :min_item_size => 48
+ },
+ :sysctl => {
+ :swappiness => {
+ :comment => "Reduce swap usage",
+ :parameters => {
+ "vm.swappiness" => 10
+ }
+ }
},
:mysql => {
:settings => {
:mysqld => {
:innodb_buffer_pool_size => "4G",
:key_buffer_size => "64M",
- :max_connections => "200",
+ :max_connections => "500",
:sort_buffer_size => "8M",
:tmp_table_size => "128M"
}
+++ /dev/null
-name "yandex"
-description "Role applied to all servers at Yandex"
-
-default_attributes(
- :hosted_by => "Yandex",
- :location => "Moscow, Russia",
- :timezone => "Europe/Moscow",
- :networking => {
- :wireguard => { :keepalive => 180 }
- }
-)
-
-override_attributes(
- :ntp => {
- :servers => ["0.ru.pool.ntp.org", "1.ru.pool.ntp.org", "europe.pool.ntp.org"]
- }
-)
-
-run_list(
- "role[ru]"
-)
default_attributes(
:networking => {
:interfaces => {
- :internal_ipv4 => {
+ :internal => {
:interface => "eno1.2801",
:role => :internal,
- :family => :inet,
- :address => "10.0.0.15"
+ :inet => {
+ :address => "10.0.0.15"
+ }
},
- :external_ipv4 => {
+ :external => {
:interface => "eno1.2800",
:role => :external,
- :family => :inet,
- :address => "193.60.236.22"
+ :inet => {
+ :address => "193.60.236.22"
+ }
}
}
},
:postgresql => {
:settings => {
:defaults => {
- :shared_buffers => "8GB",
- :maintenance_work_mem => "7144MB",
:effective_cache_size => "16GB"
}
}
},
:tile => {
:database => {
- :cluster => "12/main",
+ :cluster => "16/main",
:postgis => "3"
},
+ :mapnik => "3.1",
:styles => {
:default => {
:tile_directories => [
+++ /dev/null
-name "zcu"
-description "Role applied to all servers at University of West Bohemia"
-
-default_attributes(
- :hosted_by => "University of West Bohemia",
- :location => "Pilsen, Czech Republic"
-)
-
-override_attributes(
- :networking => {
- :nameservers => ["147.228.3.3", "147.228.52.11"]
- },
- :ntp => {
- :servers => ["0.cz.pool.ntp.org", "1.cz.pool.ntp.org", "europe.pool.ntp.org"]
- }
-)
-
-run_list(
- "role[cz]"
-)
--- /dev/null
+{
+ "id": "community",
+ "uid": "527",
+ "comment": "Community"
+}
+++ /dev/null
-{
- "id": "donate",
- "uid": "524",
- "comment": "OSMF Donations"
-}
+++ /dev/null
-{
- "id": "forum",
- "uid": "522",
- "comment": "Forum",
- "manage_home": false
-}
--- /dev/null
+{
+ "id": "overpass",
+ "uid": "528",
+ "comment": "query.openstreetmap.org",
+ "home": "/srv/query.openstreetmap.org"
+}
--- /dev/null
+{
+ "id": "wp2fa_encrypt_keys",
+ "key": "vQk0IGrkn/nvKjyY8XNOrw=="
+}
"id": "passwords",
"database": "database-password",
"admin": "admin-password",
- "key": "key",
+ "site_key": "site_key",
+ "cred_keys": "cred_keys",
+ "sign_keys": "sign_keys",
"batch": "batch"
}
--- /dev/null
+{
+ "id": "wp2fa_encrypt_keys",
+ "key": "iPWRI6ZJ6Q0CuLA8+FsVQw=="
+}
--- /dev/null
+{
+ "id": "passwords",
+ "database": "database",
+ "oauth2_client_id": "oauth2_client_id",
+ "oauth2_secret": "oauth2_secret",
+ "mail_receiver_api_key": "mail_receiver_api_key"
+}
"planetdump": "planetdump-password",
"planetdiff": "planetdiff-password",
"backup": "backup-password",
- "gpximport": "gpximport-password",
- "munin": "munin-password",
"replication": "replication-password"
}
--- /dev/null
+{
+ "id": "passwords",
+ "wiki": {
+ "database": "database_password",
+ "admin": "admin_password"
+ },
+ "board": {
+ "database": "database_password",
+ "admin": "admin_password"
+ },
+ "dwg": {
+ "database": "database_password",
+ "admin": "admin_password"
+ },
+ "mwg": {
+ "database": "database_password",
+ "admin": "admin_password"
+ }
+}
--- /dev/null
+{
+ "id": "aws",
+ "osm-pds": "osm-pds"
+}
--- /dev/null
+{
+ "id": "passwords",
+ "prometheus": "prometheus-password"
+}
"sotm2009": "sotm2009",
"sotm2010": "sotm2010",
"sotm2011": "sotm2011",
- "sotm2012": "sotm2012",
- "sotm2016": "sotm2016"
+ "sotm2012": "sotm2012"
}
--- /dev/null
+{
+ "id": "wp2fa_encrypt_keys",
+ "sotm2007": "q1bhaOUla4GIHvTp/QR5bw==",
+ "sotm2008": "VUkZ0vbiXgTu8IwZyz71Lg==",
+ "sotm2009": "8nQDE9ng6QW8AKDpsm3NOA==",
+ "sotm2010": "Bu968voFkvMpSgogWBrf6g==",
+ "sotm2011": "vsrEyBqcI30SFv9gyYkyWQ==",
+ "sotm2012": "Qe3olwbbSFuraQAoUXieHA=="
+}
--- /dev/null
+{
+ "id": "passwords",
+ "aws_key": "AWS_KEY_VALUE"
+}
{
- "id": "piwik",
- "location": "piwik",
+ "id": "matomo",
+ "location": "matomo",
"site": 100,
"goals": {
"signup": 1001,
"oauth_key": "oauth",
"google_auth_secret": "google",
"facebook_auth_secret": "facebook",
- "windowslive_auth_secret": "windowslive",
+ "microsoft_auth_secret": "microsoft",
"github_auth_secret": "github",
"wikipedia_auth_secret": "wikipedia",
"mapquest_key": "mapquest",
"mapzen_valhalla_key": "mapzen-valhalla",
"thunderforest_key": "thunderforest",
+ "tracestrack_key": "tracestrack",
"totp_key": "totp",
- "aws_key": "aws"
+ "aws_key": "aws",
+ "openid_connect_key": [
+ "-----BEGIN PRIVATE KEY-----",
+ "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC1yJqM4c0bJNVN",
+ "BLUrKA1Hmu4XoesiIjiuN9CwvVKTbtSy4CxymxaVYDarFoypwY7fOLzTU2F1En9n",
+ "B0ShiFclbRVqpAXwGH4KeKI5qcHUrZeYSKgy7MQmyvsHOF2hSuL5SOgHyhU888sN",
+ "CyFnFnBrf4jxi1crdBYPO3gQvLtxG4q0xSpDPsyKAKX8K86JGDMIJlEJTJo5esLO",
+ "QOYsZp6g3olaTlWzxafPPz26pWMIcYIW3TFa9Lj5zFtF6YAitk7KRhX+0O5T9Zfn",
+ "WDE8ZC8oQPZxIBIuBG2tvih6NpUFAeVEMCqHs6S7hYSW/Oguow36FFMeQ/snQzPy",
+ "sO+AQKaPAgMBAAECggEADT+0J+1zHfXWx/i+XYlbQmtDzBwkf4Xf/K6buq3pvU4Y",
+ "GXtmMeokwLlU8q4/jUXKrHE9redHVJmHCJLKiT1fIJ6tL2sJ9cBLO2ckZ7B8LIyE",
+ "Xnh5LdD80Nj9Z77PcCh9l26dXqf3WUxpcadshU9o3STb7cLalROuYejTLOEchjc8",
+ "sKdMW0OjzHt8qLEa5wjZ9mG6hfyMzBzYbQCYTPU67FnJun7Ssej3WWJDkgnVdx4x",
+ "hTvtVjOh3fGIE01I1qbSz4oJ+b3mvqQpCGPM3nvkKxTSlcnxr25c8V/6F7I896eW",
+ "tAyxf5R7t4p6uGWfXUtOF+nuAo9ePHkPlQ6qOQAR7QKBgQDhTHkKepttw98cIay4",
+ "N93kpDYU+hA/oKcZr/OkXye4Ym1cbV4TTFfLs/8+t67PB0kx8ONnxoTsDaxhb1Uh",
+ "qK9yonYUeiwF07Wbtc59WVtHob9h/f4J9+x1rFNgkZoaFn5AJPxmRF57HUFw8mql",
+ "1XiY3jnZxV3A9fsggyZvQU6FXQKBgQDOjhwaEov/xNsvv987nMi8rYq6uLOW1HHE",
+ "Fc5Fw9aHMAN19hnCUxS3WQowP/XT3c11/aXTbz4xpscIZfuBqmpBWgNSs1wEzBfO",
+ "STx1FY/FF3TQr3QPzUH+nKJ39hmCoOC4uwKyezvnL12nmboDYLa5N51hA+4JUlxp",
+ "nH6dUA3Q2wKBgQDaXycLEx/H2oxMVg91VyEJ1mhdGKvbIDoW2caL0XdMboqVhaQj",
+ "jGGknciO37beD6/Qai3gjjiUHASzRBf90eSMdg+BdZFp7HQggq2sLYod+hboQimT",
+ "O+zDec4u0bHOC3M/dRn3fdkd95NQiIb6SdjkQrFL9NMUjtdkAfqk52XWOQKBgQCy",
+ "7708gPCzJBBVrzxt4gasHRLfav55HZVorxNAsMT53AhDem0aQOrjYslGv0Hwxmcl",
+ "XhT3s5kHXllx1xcoXz8pWhci36pJpZzB4gPz0jf4H7fcyQIcZk5TidHdZl73IPNM",
+ "VQWjJMriHdBeTvgr0O66SYmW79aYULcp7p5pHV66nQKBgQDSGUHJ0/QMe57kb5SE",
+ "ftJBefU7R7b5VKmQjouGjUFFr4pkBg+6+Y7WiqiM5ttDQNsd3x2Eqwh2Zk+cSJSh",
+ "WePy2Q+V52Bu23rf43BO6NKzEtpcKCPbelMsdHGL35huzJEIXlisouIGhlV8NKjT",
+ "wlbD0G8f/zHjhf8cNhmQKJt0sQ==",
+ "-----END PRIVATE KEY-----"
+ ]
}
{
"database": "database_password",
"admin": "admin_password",
- "recaptcha": "precaptcha_token",
+ "hcaptcha": "precaptcha_token",
"thunderforest": "thunderforest_token"
}
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("apache2") do
it { should be_installed }
end
end
describe port(80) do
- it { should be_listening.with("tcp") }
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
end
describe port(443) do
- it { should be_listening.with("tcp") }
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
end
--- /dev/null
+describe command("/opt/awscli/v2/current/bin/aws --version") do
+ its("exit_status") { should eq 0 }
+end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("bind9") do
it { should be_installed }
end
end
describe port(53) do
- it { should be_listening.with("udp") }
- it { should be_listening.with("tcp") }
+ it { should be_listening }
+ its("protocols") { should cmp %w[udp udp6 tcp tcp6] }
end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("apache2") do
it { should be_installed }
end
end
describe port(80) do
- it { should be_listening.with("tcp") }
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
end
describe port(443) do
- it { should be_listening.with("tcp") }
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
end
--- /dev/null
+describe command("/opt/wp-cli/wp --allow-root --path=/srv/blog.openstreetmap.org/wp/ core is-installed") do
+ its("exit_status") { should eq 0 }
+end
+
+describe command("/opt/wp-cli/wp --allow-root --path=/srv/blog.openstreetmap.org/wp/ plugin is-active wp-fail2ban") do
+ its("exit_status") { should eq 0 }
+end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("apache2") do
it { should be_installed }
end
end
describe port(80) do
- it { should be_listening.with("tcp") }
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
end
describe port(443) do
- it { should be_listening.with("tcp") }
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
end
--- /dev/null
+describe package("chef") do
+ it { should be_installed }
+end
+
+describe systemd_service("chef-client") do
+ it { should be_installed }
+end
+
+describe systemd_service("chef-client.timer") do
+ it { should be_installed }
+ it { should be_enabled }
+end
+
+describe command("chef-client --version") do
+ its("exit_status") { should eq 0 }
+ its("stdout") { should match /Chef Infra Client/ }
+end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("apache2") do
it { should be_installed }
end
end
describe port(80) do
- it { should be_listening.with("tcp") }
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
end
describe port(443) do
- it { should be_listening.with("tcp") }
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("clamav-daemon") do
it { should be_installed }
end
--- /dev/null
+describe package("docker-ce") do
+ it { should be_installed }
+end
+
+describe service("docker") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe docker_image("local_discourse/data:latest") do
+ it { should exist }
+end
+
+describe docker_image("local_discourse/mail-receiver:latest") do
+ it { should exist }
+end
+
+describe docker_image("local_discourse/web_only:latest") do
+ it { should exist }
+end
--- /dev/null
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp %w[tcp tcp6] }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp %w[tcp tcp6] }
+end
--- /dev/null
+describe service("backup-db.timer") do
+ it { should be_enabled }
+ it { should be_running }
+end
--- /dev/null
+describe package("postgresql-15") do
+ it { should be_installed }
+end
+
+describe service("postgresql@15-main") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(5432) do
+ it { should be_listening }
+ its("protocols") { should cmp %w[tcp tcp6] }
+end
--- /dev/null
+describe package("postgresql-15") do
+ it { should be_installed }
+end
+
+describe service("postgresql@15-main") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(5432) do
+ it { should be_listening }
+ its("protocols") { should cmp %w[tcp tcp6] }
+end
--- /dev/null
+describe package("postgresql-15") do
+ it { should be_installed }
+end
+
+describe service("postgresql@15-main") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(5432) do
+ it { should be_listening }
+ its("protocols") { should cmp %w[tcp tcp6] }
+end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("isc-dhcp-server") do
it { should be_installed }
end
end
describe port(67) do
- it { should be_listening.with("udp") }
+ it { should be_listening }
+ its("protocols") { should cmp "udp" }
end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
--- /dev/null
+describe package("dnscontrol") do
+ it { should be_installed }
+end
+
+describe command("dnscontrol version") do
+ its(:exit_status) { should eq 0 }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
--- /dev/null
+describe package("docker-ce") do
+ it { should be_installed }
+end
+
+describe service("docker") do
+ it { should be_enabled }
+ it { should be_running }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("mysql-server") do
- it { should be_installed }
-end
-
-describe service("mysql") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(3306) do
- it { should be_listening.with("tcp") }
-end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("elasticsearch") do
it { should be_installed }
end
end
# describe port(9200) do
-# it { should be_listening.with("tcp") }
+# it { should be_listening }
+# its("protocols") { should cmp "tcp" }
# end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("exim4") do
it { should be_installed }
end
end
describe port(25) do
- it { should be_listening.with("tcp") }
+ it { should be_listening }
+ its("protocols") { should cmp %w[tcp tcp6] }
end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("fail2ban") do
it { should be_installed }
end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("mysql-server") do
- it { should be_installed }
-end
-
-describe service("mysql") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(3306) do
- it { should be_listening.with("tcp") }
-end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("vsftpd") do
it { should be_installed }
end
end
describe port(21) do
- it { should be_listening.with("tcp6") }
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("gdnsd") do
it { should be_installed }
end
end
describe port(53) do
- it { should be_listening.with("udp") }
- it { should be_listening.with("tcp") }
+ it { should be_listening }
+ its("protocols") { should cmp %w[udp tcp] }
end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
--- /dev/null
+describe package("gitweb") do
+ it { should be_installed }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("gitweb") do
- it { should be_installed }
-end
--- /dev/null
+describe package("git") do
+ it { should be_installed }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("git") do
- it { should be_installed }
-end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe service("gps-update") do
it { should be_enabled }
it { should be_running }
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
--- /dev/null
+describe package("nginx") do
+ it { should be_installed }
+end
+
+describe service("nginx") do
+ it { should be_enabled }
+ it { should be_running }
+end
--- /dev/null
+describe package("nginx") do
+ it { should be_installed }
+end
+
+describe service("nginx") do
+ it { should be_enabled }
+ it { should be_running }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("incron") do
- it { should be_installed }
-end
-
-describe service("incron") do
- it { should be_enabled }
- it { should be_running }
-end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("filebeat") do
it { should be_installed }
end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("elasticsearch") do
it { should be_installed }
end
end
# describe port(9200) do
-# it { should be_listening.with("tcp") }
+# it { should be_listening }
+# its("protocols") { should cmp "tcp" }
# end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("logstash") do
it { should be_installed }
end
end
# describe port(5044) do
-# it { should be_listening.with("tcp") }
+# it { should be_listening }
+# its("protocols") { should cmp "tcp" }
# end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("clamav-daemon") do
it { should be_installed }
end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("exim4") do
it { should be_installed }
end
end
describe port(25) do
- it { should be_listening.with("tcp") }
+ it { should be_listening }
+ its("protocols") { should cmp %w[tcp tcp6] }
end
--- /dev/null
+service_name = if os.name == "debian"
+ "spamd"
+ else
+ "spamassassin"
+ end
+
+describe package("spamassassin") do
+ it { should be_installed }
+end
+
+describe service(service_name) do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(783) do
+ it { should be_listening }
+ its("protocols") { should cmp %w[tcp tcp6] }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("spamassassin") do
- it { should be_installed }
-end
-
-describe service("spamassassin") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(783) do
- it { should be_listening.with("tcp") }
-end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("mailman") do
it { should be_installed }
end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("memcached") do
it { should be_installed }
end
end
describe port(11211) do
- it { should be_listening.with("tcp") }
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("munin") do
- it { should be_installed }
-end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("rrdcached") do
- it { should be_installed }
-end
-
-describe service("rrdcached") do
- it { should be_enabled }
- it { should be_running }
-end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("munin-node") do
- it { should be_installed }
-end
-
-describe service("munin-node") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(4949) do
- it { should be_listening.with("tcp6") }
-end
--- /dev/null
+mysql_variant = if os.name == "ubuntu"
+ "mysql"
+ else
+ "mariadb"
+ end
+
+describe package("#{mysql_variant}-server") do
+ it { should be_installed }
+end
+
+describe service("#{mysql_variant}") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(3306) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("mysql-server") do
- it { should be_installed }
-end
-
-describe service("mysql") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(3306) do
- it { should be_listening.with("tcp") }
-end
--- /dev/null
+describe package("nftables") do
+ it { should be_installed }
+end
+
+describe service("nftables") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe file("/etc/nftables.conf") do
+ it { should be_file }
+ its(:content) { should match(/echo-request.*accept/) }
+ its(:content) { should match(/http.*accept/) }
+ its(:content) { should match(/https.*accept/) }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("shorewall") do
- it { should be_installed }
-end
-
-describe service("shorewall") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe file("/etc/shorewall/rules") do
- it { should be_file }
- its(:content) { should match(/ACCEPT.*echo-request/) }
- its(:content) { should match(/ACCEPT.*http/) }
- its(:content) { should match(/ACCEPT.*https/) }
-end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("nginx") do
it { should be_installed }
end
end
describe port(8050) do
- it { should be_listening.with("tcp") }
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("nodejs") do
it { should be_installed }
end
-describe package("npm") do
+describe package("yarn") do
it { should be_installed }
end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("nginx") do
it { should be_installed }
end
end
describe port(8050) do
- it { should be_listening.with("tcp") }
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("chrony") do
it { should be_installed }
end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("openssh-client") do
it { should be_installed }
end
end
describe port(22) do
- it { should be_listening.with("tcp") }
+ it { should be_listening }
+ its("protocols") { should cmp %w[tcp tcp6] }
end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe file("/usr/local/bin/osmosis") do
it { should be_symlink }
end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
--- /dev/null
+describe file("/opt/planet-dump-ng/planet-dump-ng") do
+ it { should be_file }
+ it { should be_executable }
+end
+
+describe file("/usr/local/bin/planetdump") do
+ it { should be_file }
+ it { should be_executable }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe file("/opt/planet-dump-ng/planet-dump-ng") do
- it { should be_file }
- it { should be_executable }
-end
-
-describe file("/usr/local/bin/planetdump") do
- it { should be_file }
- it { should be_executable }
-end
-
-describe file("/usr/local/bin/planet-mirror-redirect-update") do
- it { should be_file }
- it { should be_executable }
-end
-
-describe file("/etc/cron.d/planet-dump-mirror") do
- it { should be_file }
-end
--- /dev/null
+describe file("/usr/local/bin/planet-notes-dump") do
+ it { should be_file }
+ it { should be_executable }
+end
+
+describe service("planet-notes-dump.timer") do
+ it { should be_enabled }
+ it { should be_running }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe file("/usr/local/bin/planet-notes-dump") do
- it { should be_file }
- it { should be_executable }
-end
-
-describe file("/etc/cron.d/planet-notes-dump") do
- it { should be_file }
-end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe http("http://localhost") do
+ its("status") { should cmp 200 }
+end
+
+# Minutely Replication Diffs
+
+describe http("https://127.0.0.1/replication/minute/state.txt",
+ :headers => { "Host" => "planet.openstreetmap.org" },
+ :ssl_verify => false) do
+ its("status") { should eq 302 }
+ its("headers.Location") { should eq "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/planet/replication/minute/state.txt" }
+end
+
+describe http("https://127.0.0.1/replication/changesets/001/002/003.state.txt",
+ :headers => { "Host" => "planet.openstreetmap.org" },
+ :ssl_verify => false) do
+ its("status") { should eq 302 }
+ its("headers.Location") { should eq "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/changesets/replication/minute/001/002/003.state.txt" }
+end
+
+describe http("https://127.0.0.1/replication/minute/001/002/003.osc.gz",
+ :headers => { "Host" => "planet.openstreetmap.org" },
+ :ssl_verify => false) do
+ its("status") { should eq 302 }
+ its("headers.Location") { should eq "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/planet/replication/minute/001/002/003.osc.gz" }
+end
+
+# Hourly Replication Diffs
+
+describe http("https://127.0.0.1/replication/hour/state.txt",
+ :headers => { "Host" => "planet.openstreetmap.org" },
+ :ssl_verify => false) do
+ its("status") { should eq 302 }
+ its("headers.Location") { should eq "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/planet/replication/hour/state.txt" }
+end
+
+describe http("https://127.0.0.1/replication/hour/001/002/003.state.txt",
+ :headers => { "Host" => "planet.openstreetmap.org" },
+ :ssl_verify => false) do
+ its("status") { should eq 302 }
+ its("headers.Location") { should eq "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/planet/replication/hour/001/002/003.state.txt" }
+end
+
+describe http("https://127.0.0.1/replication/minute/001/002/003.osc.gz",
+ :headers => { "Host" => "planet.openstreetmap.org" },
+ :ssl_verify => false) do
+ its("status") { should eq 302 }
+ its("headers.Location") { should eq "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/planet/replication/minute/001/002/003.osc.gz" }
+end
+
+# Daily Replication Diffs
+
+describe http("https://127.0.0.1/replication/day/state.txt",
+ :headers => { "Host" => "planet.openstreetmap.org" },
+ :ssl_verify => false) do
+ its("status") { should eq 302 }
+ its("headers.Location") { should eq "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/planet/replication/day/state.txt" }
+end
+
+describe http("https://127.0.0.1/replication/day/001/002/003.state.txt",
+ :headers => { "Host" => "planet.openstreetmap.org" },
+ :ssl_verify => false) do
+ its("status") { should eq 302 }
+ its("headers.Location") { should eq "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/planet/replication/day/001/002/003.state.txt" }
+end
+
+describe http("https://127.0.0.1/replication/day/001/002/003.osc.gz",
+ :headers => { "Host" => "planet.openstreetmap.org" },
+ :ssl_verify => false) do
+ its("status") { should eq 302 }
+ its("headers.Location") { should eq "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/planet/replication/day/001/002/003.osc.gz" }
+end
+
+# Changeset Replication Diffs
+
+describe http("https://127.0.0.1/replication/changesets/state.yaml",
+ :headers => { "Host" => "planet.openstreetmap.org" },
+ :ssl_verify => false) do
+ its("status") { should eq 302 }
+ its("headers.Location") { should eq "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/changesets/replication/minute/state.yaml" }
+end
+
+describe http("https://127.0.0.1/replication/changesets/001/002/003.state.txt",
+ :headers => { "Host" => "planet.openstreetmap.org" },
+ :ssl_verify => false) do
+ its("status") { should eq 302 }
+ its("headers.Location") { should eq "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/changesets/replication/minute/001/002/003.state.txt" }
+end
+
+describe http("https://127.0.0.1/replication/changesets/001/002/003.osm.gz",
+ :headers => { "Host" => "planet.openstreetmap.org" },
+ :ssl_verify => false) do
+ its("status") { should eq 302 }
+ its("headers.Location") { should eq "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/changesets/replication/minute/001/002/003.osm.gz" }
+end
+
+# Planet File
+
+describe http("https://127.0.0.1/planet/2023/planet-231016.osm.bz2",
+ :headers => { "Host" => "planet.openstreetmap.org" },
+ :ssl_verify => false) do
+ its("status") { should eq 302 }
+ its("headers.Location") { should eq "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/planet/osm/2023/planet-231016.osm.bz2" }
+end
+
+# Planet File MD5
+
+describe http("https://127.0.0.1/planet/2023/planet-231016.osm.bz2.md5",
+ :headers => { "Host" => "planet.openstreetmap.org" },
+ :ssl_verify => false) do
+ its("status") { should eq 302 }
+ its("headers.Location") { should eq "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/planet/osm/2023/planet-231016.osm.bz2.md5" }
+end
+
+# Full History Planet File
+
+describe http("https://127.0.0.1/planet/full-history/2023/history-231016.osm.bz2",
+ :headers => { "Host" => "planet.openstreetmap.org" },
+ :ssl_verify => false) do
+ its("status") { should eq 302 }
+ its("headers.Location") { should eq "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/planet-full-history/osm/2023/history-231016.osm.bz2" }
+end
+
+# Full History Planet File MD5
+
+describe http("https://127.0.0.1/planet/full-history/2023/history-231016.osm.bz2.md5",
+ :headers => { "Host" => "planet.openstreetmap.org" },
+ :ssl_verify => false) do
+ its("status") { should eq 302 }
+ its("headers.Location") { should eq "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/planet-full-history/osm/2023/history-231016.osm.bz2.md5" }
+end
+
+# PBF planet file
+
+describe http("https://127.0.0.1/pbf/planet-231016.osm.pbf",
+ :headers => { "Host" => "planet.openstreetmap.org" },
+ :ssl_verify => false) do
+ its("status") { should eq 302 }
+ its("headers.Location") { should eq "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/planet/pbf/2023/planet-231016.osm.pbf" }
+end
+
+# PBF full history planet file
+
+describe http("https://127.0.0.1/pbf/full-history/history-231016.osm.pbf",
+ :headers => { "Host" => "planet.openstreetmap.org" },
+ :ssl_verify => false) do
+ its("status") { should eq 302 }
+ its("headers.Location") { should eq "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/planet-full-history/pbf/2023/history-231016.osm.pbf" }
+end
+
+# Notes file
+
+describe http("https://127.0.0.1/notes/2023/planet-notes-231222.osn.bz2",
+ :headers => { "Host" => "planet.openstreetmap.org" },
+ :ssl_verify => false) do
+ its("status") { should eq 302 }
+ its("headers.Location") { should eq "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/notes/osn/2023/planet-notes-231222.osn.bz2" }
+end
+
+describe http("https://127.0.0.1/notes/2023/planet-notes-231222.osn.bz2.md5",
+ :headers => { "Host" => "planet.openstreetmap.org" },
+ :ssl_verify => false) do
+ its("status") { should eq 302 }
+ its("headers.Location") { should eq "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/notes/osn/2023/planet-notes-231222.osn.bz2.md5" }
+end
+
+# Tiles log
+
+describe http("https://127.0.0.1/tile_logs/tiles-2023-10-21.txt.xz",
+ :headers => { "Host" => "planet.openstreetmap.org" },
+ :ssl_verify => false) do
+ its("status") { should eq 302 }
+ its("headers.Location") { should eq "https://osm-planet-eu-central-1.s3.dualstack.eu-central-1.amazonaws.com/tile_logs/standard_layer/tiles/2023/tiles-2023-10-21.txt.xz" }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
--- /dev/null
+describe package("postgresql-15") do
+ it { should be_installed }
+end
+
+describe service("postgresql@15-main") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(5432) do
+ it { should be_listening }
+ its("protocols") { should cmp %w[tcp tcp6] }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("postgresql-10") do
- it { should be_installed }
-end
-
-describe service("postgresql@10-main") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(5432) do
- it { should be_listening.with("tcp") }
-end
--- /dev/null
+describe service("prometheus-alertmanager") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(9093) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("grafana-enterprise") do
it { should be_installed }
end
end
describe port(3000) do
- it { should be_listening.with("tcp6") }
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
end
--- /dev/null
+describe service("prometheus-karma") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(8081) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("prometheus") do
it { should be_installed }
end
end
describe port(9090) do
- it { should be_listening.with("tcp6") }
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("prometheus-alertmanager") do
- it { should be_installed }
-end
-
-describe service("prometheus-alertmanager") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(9093) do
- it { should be_listening.with("tcp6") }
-end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe service("promscale") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(9201) do
- it { should be_listening.with("tcp6") }
-end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe service("prometheus-node-exporter") do
it { should be_enabled }
it { should be_running }
end
describe port(9100) do
- it { should be_listening.with("tcp") }
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("rsync") do
it { should be_installed }
end
end
describe port(873) do
- it { should be_listening.with("tcp") }
+ it { should be_listening }
+ its("protocols") { should cmp %w[tcp tcp6] }
end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("snmpd") do
it { should be_installed }
end
end
describe port(161) do
- it { should be_listening.with("udp") }
+ it { should be_listening }
+ its("protocols") { should cmp %w[udp] }
end
--- /dev/null
+service_name = if os.name == "debian"
+ "spamd"
+ else
+ "spamassassin"
+ end
+
+describe package("spamassassin") do
+ it { should be_installed }
+end
+
+describe service(service_name) do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(783) do
+ it { should be_listening }
+ its("protocols") { should cmp %w[tcp tcp6] }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("spamassassin") do
- it { should be_installed }
-end
-
-describe service("spamassassin") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(783) do
- it { should be_listening.with("tcp") }
-end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("squid") do
- it { should be_installed }
-end
-
-describe service("squid") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(3128) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(8080) do
- it { should be_listening.with("tcp") }
-end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("subversion") do
- it { should be_installed }
-end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("limnoria") do
it { should be_installed }
end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("sysfsutils") do
it { should be_installed }
end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("nginx") do
- it { should be_installed }
-end
-
-describe service("nginx") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(8050) do
- it { should be_listening.with("tcp") }
-end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("squid") do
- it { should be_installed }
-end
-
-describe service("squid") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(3128) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(8080) do
- it { should be_listening.with("tcp") }
-end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe service("cgimap") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(8000) do
- it { should be_listening.with("tcp") }
-end
--- /dev/null
+describe service("cgimap") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe file("/run/cgimap/socket") do
+ it { should be_socket }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe service("cgimap") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(8000) do
- it { should be_listening.with("tcp") }
-end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
--- /dev/null
+describe service("cgimap") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe file("/run/cgimap/socket") do
+ it { should be_socket }
+end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe package("memcached") do
it { should be_installed }
end
end
describe port(11211) do
- it { should be_listening.with("tcp") }
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe service("api-statistics") do
it { should be_enabled }
it { should be_running }
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe service("cgimap") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(8000) do
- it { should be_listening.with("tcp") }
-end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
describe service("api-statistics") do
it { should be_enabled }
it { should be_running }
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe service("api-statistics") do
- it { should be_enabled }
- it { should be_running }
-end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end
--- /dev/null
+describe package("apache2") do
+ it { should be_installed }
+end
+
+describe service("apache2") do
+ it { should be_enabled }
+ it { should be_running }
+end
+
+describe port(80) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+
+describe port(443) do
+ it { should be_listening }
+ its("protocols") { should cmp "tcp" }
+end
+++ /dev/null
-require "serverspec"
-
-# Required by serverspec
-set :backend, :exec
-
-describe package("apache2") do
- it { should be_installed }
-end
-
-describe service("apache2") do
- it { should be_enabled }
- it { should be_running }
-end
-
-describe port(80) do
- it { should be_listening.with("tcp") }
-end
-
-describe port(443) do
- it { should be_listening.with("tcp") }
-end