Skip to content

Commit

Permalink
Create a new vectortile role
Browse files Browse the repository at this point in the history
This role is for tilekiln vector tile servers and it currently
sets up and starts tilekiln and has the scripts necessary to
import data.
  • Loading branch information
pnorman committed Aug 9, 2024
1 parent 8668f1a commit 56dfbbf
Show file tree
Hide file tree
Showing 26 changed files with 655 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .kitchen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,9 @@ suites:
- name: trac
run_list:
- recipe[trac::default]
- name: vectortile
run_list:
- recipe[vectortile::default]
- name: web-cgimap
run_list:
- recipe[web::cgimap]
Expand Down
16 changes: 16 additions & 0 deletions cookbooks/postgresql/libraries/postgresql.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ module OpenStreetMap
class PostgreSQL
include Chef::Mixin::ShellOut

SCHEMA_PRIVILEGES = [
:create, :usage
].freeze

TABLE_PRIVILEGES = [
:select, :insert, :update, :delete, :truncate, :references, :trigger
].freeze
Expand Down Expand Up @@ -115,6 +119,18 @@ def tablespaces
end
end

def schemas(database)
@schemas ||= {}
@schemas[database] ||= query("SELECT n.nspname, pg_catalog.pg_get_userbyid(n.nspowner) AS usename, n.nspacl FROM pg_namespace AS n WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema'", :database => database).each_with_object({}) do |schema, schemas|
name = "#{schema[:nspname]}"

schemas[name] = {
:owner => schema[:usename],
:permissions => parse_acl(schema[:nspacl] || "{}")
}
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 WHERE n.nspname NOT IN ('pg_catalog', 'information_schema') AND c.relkind = 'r'", :database => database).each_with_object({}) do |table, tables|
Expand Down
114 changes: 114 additions & 0 deletions cookbooks/postgresql/resources/schema.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#
# Cookbook:: postgresql
# Resource:: postgresql_schema
#
# 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.
#

unified_mode true

default_action :create

property :schema, :kind_of => String, :name_property => true
property :cluster, :kind_of => String, :required => true
property :database, :kind_of => String, :required => true
property :owner, :kind_of => String, :required => [:create]
property :permissions, :kind_of => Hash, :default => {}

action :create do
if schemas.include?(qualified_name)
# Handle the case of an existing schema
if new_resource.owner != schemas[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 SCHEMA #{qualified_name} OWNER TO \"#{new_resource.owner}\"", :database => new_resource.database)
end
end

schemas[qualified_name][:permissions].each_key do |user|
next if new_resource.permissions[user]
# Remove permissions from users who no longer have them
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 SCHEMA #{qualified_name} FROM \"#{user}\"", :database => new_resource.database)
end
end
new_resource.permissions.each do |user, new_privileges|
current_privileges = schemas[qualified_name][:permissions][user] || {}
new_privileges = Array(new_privileges)

if new_privileges.include?(:all)
new_privileges |= OpenStreetMap::PostgreSQL::SCHEMA_PRIVILEGES
end

OpenStreetMap::PostgreSQL::SCHEMA_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 SCHEMA #{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 SCHEMA #{qualified_name} FROM \"#{user}\"", :database => new_resource.database)
end
end
end
end
else
converge_by "create schema #{new_resource.schema}" do
cluster.execute(:command => "CREATE SCHEMA #{new_resource.schema} AUTHORIZATION #{new_resource.owner}", :database => new_resource.database)
# Because the schema is new, we don't have to worry about revoking or checking current permissions
new_resource.permissions.each do |user, new_privileges|
new_privileges = Array(new_privileges)
if new_privileges.include?(:all)
new_privileges |= OpenStreetMap::PostgreSQL::SCHEMA_PRIVILEGES
end
OpenStreetMap::PostgreSQL::SCHEMA_PRIVILEGES.each do |privilege|
next unless new_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 SCHEMA #{qualified_name} TO \"#{user}\"", :database => new_resource.database)
end
end
end
end
end
end

action :drop do
if schemas.include?(qualified_name)
converge_by("drop #{new_resource}") do
Chef::Log.info("Dropping #{new_resource}")
cluster.execute(:command => "DROP SCHEMA #{qualified_name}", :database => new_resource.database)
end
end
end

action_class do
def cluster
@cluster ||= OpenStreetMap::PostgreSQL.new(new_resource.cluster)
end

def schemas
@schemas ||= cluster.schemas(new_resource.database)
end

def qualified_name
"#{new_resource.name}"
end
end
9 changes: 9 additions & 0 deletions cookbooks/vectortile/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# vectortile cookbook

This cookbook installs and configures the tilekiln based tileservers

## Accounts
The following accounts are used
- `www-data` for nginx serving static files and proxying
- `tilekiln` for the process serving tiles
- `update` for the process running osm2pgsql and tilekiln on updates
9 changes: 9 additions & 0 deletions cookbooks/vectortile/attributes/default.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
default[:vectortile][:database][:cluster] = "16/main"
default[:vectortile][:database][:postgis] = "3"
default[:vectortile][:serve][:threads] = node.cpu_cores

default[:postgresql][:versions] |= [node[:vectortile][:database][:cluster].split("/").first]
default[:postgresql][:monitor_database] = "tiles"

default[:accounts][:users][:tileupdate][:status] = :role
default[:accounts][:users][:tilekiln][:status] = :role
13 changes: 13 additions & 0 deletions cookbooks/vectortile/files/default/html/clientaccesspolicy.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="*">
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
5 changes: 5 additions & 0 deletions cookbooks/vectortile/files/default/html/crossdomain.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?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="*" secure="false" />
</cross-domain-policy>
Binary file not shown.
13 changes: 13 additions & 0 deletions cookbooks/vectortile/files/default/html/robots.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
User-agent: *
Disallow: /12/
Disallow: /13/
Disallow: /14/
Disallow: /15/
Disallow: /16/
Disallow: /17/
Disallow: /18/
Disallow: /19/
Disallow: /20/
Disallow: /21/
Disallow: /22/
Disallow: /23/
16 changes: 16 additions & 0 deletions cookbooks/vectortile/metadata.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name "vectortile"
maintainer "OpenStreetMap Administrators"
maintainer_email "[email protected]"
license "Apache-2.0"
description "Installs and configures vector tile servers"

version "1.0.0"
supports "ubuntu"
depends "accounts"
depends "git"
depends "nginx"
depends "postgresql"
depends "prometheus"
depends "python"
depends "systemd"
depends "tools"
Loading

0 comments on commit 56dfbbf

Please sign in to comment.